From 4698f91320d4aafd6081f3c5b0c06a0b5080d74e Mon Sep 17 00:00:00 2001 From: Siddharth Zaveri Date: Tue, 13 Oct 2015 17:14:05 -0400 Subject: [PATCH] msm: Bringup 2 instances of ADV7533 for 8996 Bringup 2 instances of ADV7533 for 8996. Change all register writes from constant to pdata variables. Move the DBA init from mdss_dsi.c to mdss_dsi_panel.c. Change-Id: Ib0fc9f7c2348efa04a44bc021cb50973e90d7f22 Signed-off-by: Siddharth Zaveri [cip@codeaurora.org: Removed spurious drivers/video/msm/Makefile change] Signed-off-by: Clarence Ip --- drivers/video/fbdev/msm/mdss_dsi.c | 269 +---------- drivers/video/fbdev/msm/mdss_dsi.h | 4 +- drivers/video/fbdev/msm/mdss_dsi_panel.c | 155 +++++- drivers/video/fbdev/msm/msm_dba/Kconfig | 2 +- drivers/video/fbdev/msm/msm_dba/adv7533.c | 452 ++++++++++++------ .../video/fbdev/msm/msm_dba/msm_dba_debug.c | 69 ++- .../video/fbdev/msm/msm_dba/msm_dba_init.c | 3 +- .../fbdev/msm/msm_dba/msm_dba_internal.h | 7 + 8 files changed, 533 insertions(+), 428 deletions(-) diff --git a/drivers/video/fbdev/msm/mdss_dsi.c b/drivers/video/fbdev/msm/mdss_dsi.c index 2f9299ce9176..f8221507bfc6 100644 --- a/drivers/video/fbdev/msm/mdss_dsi.c +++ b/drivers/video/fbdev/msm/mdss_dsi.c @@ -2051,249 +2051,6 @@ int mdss_dsi_register_recovery_handler(struct mdss_dsi_ctrl_pdata *ctrl, return 0; } -static struct mdss_dsi_ctrl_pdata *mdss_dsi_get_drvdata_from_panel_data( - struct mdss_panel_data *mpd) -{ - struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; - - if (!mpd) { - pr_err("%s: Invalid panel data\n", __func__); - goto end; - } - - ctrl_pdata = container_of(mpd, struct mdss_dsi_ctrl_pdata, - panel_data); -end: - return ctrl_pdata; -} - -static struct mdss_dsi_ctrl_pdata *mdss_dsi_get_drvdata_from_sysfs_dev( - struct device *device) -{ - struct msm_fb_data_type *mfd = NULL; - struct mdss_panel_data *panel_data = NULL; - struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; - struct fb_info *fbi; - - if (!device) { - pr_err("%s: Invalid device data\n", __func__); - goto end; - } - - fbi = dev_get_drvdata(device); - if (!fbi) { - pr_err("%s: Invalid fbi data\n", __func__); - goto end; - } - - mfd = (struct msm_fb_data_type *)fbi->par; - if (!mfd) { - pr_err("%s: Invalid mfd data\n", __func__); - goto end; - } - - panel_data = dev_get_platdata(&mfd->pdev->dev); - if (!panel_data) { - pr_err("%s: Invalid panel data\n", __func__); - goto end; - } - - ctrl_pdata = mdss_dsi_get_drvdata_from_panel_data(panel_data); - -end: - return ctrl_pdata; -} - -static ssize_t mdss_dsi_sysfs_rda_connected(struct device *dev, - struct device_attribute *attr, char *buf) -{ - ssize_t ret; - struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; - - if (!dev) { - DEV_ERR("%s: invalid device\n", __func__); - return -EINVAL; - } - - ctrl_pdata = mdss_dsi_get_drvdata_from_sysfs_dev(dev); - - if (!ctrl_pdata) { - DEV_ERR("%s: invalid input\n", __func__); - return -EINVAL; - } - - ret = snprintf(buf, PAGE_SIZE, "%d\n", ctrl_pdata->hpd_state); - pr_debug("%s: '%d'\n", __func__, ctrl_pdata->hpd_state); - - return ret; -} - -static DEVICE_ATTR(connected, S_IRUGO, mdss_dsi_sysfs_rda_connected, NULL); -static struct attribute *mdss_dsi_fs_attrs[] = { - &dev_attr_connected.attr, - NULL, -}; - -static struct attribute_group mdss_dsi_fs_attrs_group = { - .attrs = mdss_dsi_fs_attrs, -}; - -static int mdss_dsi_sysfs_create(struct kobject *kobj) -{ - int rc; - - if (!kobj) { - DEV_ERR("%s: invalid input\n", __func__); - return -ENODEV; - } - - rc = sysfs_create_group(kobj, &mdss_dsi_fs_attrs_group); - if (rc) { - pr_err("%s: failed, rc=%d\n", __func__, rc); - return rc; - } - - return 0; -} - -static inline void mdss_dsi_send_cable_notification( - struct mdss_dsi_ctrl_pdata *ctrl_pdata, int val) -{ - int state = 0; - - if (!ctrl_pdata) { - DEV_ERR("%s: invalid input\n", __func__); - return; - } - state = ctrl_pdata->sdev.state; - - switch_set_state(&ctrl_pdata->sdev, val); - - DEV_INFO("%s: cable state %s %d\n", __func__, - ctrl_pdata->sdev.state == state ? - "is same" : "switched to", - ctrl_pdata->sdev.state); -} - -static void mdss_dsi_dba_cb(void *data, enum msm_dba_callback_event event) -{ - int ret = -EINVAL; - struct mdss_dsi_ctrl_pdata *ctrl_pdata = - (struct mdss_dsi_ctrl_pdata *) data; - - if (!ctrl_pdata) { - pr_err("%s: Invalid data\n", __func__); - return; - } - - switch (event) { - case MSM_DBA_CB_HPD_CONNECT: - ctrl_pdata->hpd_state = true; - - if (ctrl_pdata->dba_ops.get_raw_edid) - ret = ctrl_pdata->dba_ops.get_raw_edid( - ctrl_pdata->dba_data, - sizeof(ctrl_pdata->edid_buf), - ctrl_pdata->edid_buf, 0); - - if (!ret) - hdmi_edid_parser(ctrl_pdata->edid_data); - - mdss_dsi_send_cable_notification(ctrl_pdata, 1); - break; - - case MSM_DBA_CB_HPD_DISCONNECT: - mdss_dsi_send_cable_notification(ctrl_pdata, 0); - ctrl_pdata->hpd_state = false; - break; - - default: - break; - } -} - -static void mdss_dsi_ctrl_init_dba(struct mdss_dsi_ctrl_pdata *ctrl_pdata) -{ - struct hdmi_edid_init_data edid_init_data; - struct fb_info *fbi; - msm_dba_cb dba_cb = mdss_dsi_dba_cb; - - if (!ctrl_pdata) { - pr_err("%s: Invalid ctrl data\n", __func__); - goto end; - } - - fbi = ctrl_pdata->fbi; - if (!fbi) { - pr_err("%s: Invalid fbi data\n", __func__); - goto end; - } - - strlcpy(ctrl_pdata->dba_info.client_name, "dsi", - MSM_DBA_CLIENT_NAME_LEN); - - strlcpy(ctrl_pdata->dba_info.chip_name, "adv7533", - MSM_DBA_CHIP_NAME_MAX_LEN); - - ctrl_pdata->dba_info.instance_id = 0; - ctrl_pdata->dba_info.cb = dba_cb; - ctrl_pdata->dba_info.cb_data = ctrl_pdata; - - ctrl_pdata->dba_data = msm_dba_register_client( - &ctrl_pdata->dba_info, - &ctrl_pdata->dba_ops); - - if (IS_ERR_OR_NULL(ctrl_pdata->dba_data)) { - pr_err("%s: ds not configured\n", __func__); - goto end; - } - - if (mdss_dsi_sysfs_create(&fbi->dev->kobj)) { - pr_err("%s:sysfs creation failed\n", - __func__); - goto end; - } - - ctrl_pdata->sdev.name = "dsi"; - if (switch_dev_register(&ctrl_pdata->sdev) < 0) { - pr_err("%s: DSI switch registration failed\n", - __func__); - goto end; - } - - /* Initialize EDID feature */ - edid_init_data.kobj = &fbi->dev->kobj; - edid_init_data.ds_data = NULL; - - ctrl_pdata->edid_data = hdmi_edid_init(&edid_init_data); - if (!ctrl_pdata->edid_data) { - pr_err("%s: edid parser init failed\n", __func__); - goto end; - } - - if (ctrl_pdata->dba_ops.power_on) - ctrl_pdata->dba_ops.power_on(ctrl_pdata->dba_data, - true, 0); - - ctrl_pdata->ds_registered = true; -end: - return; -} - -static void mdss_dsi_dba_work(struct work_struct *work) -{ - struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; - struct delayed_work *dw = to_delayed_work(work); - - ctrl_pdata = container_of(dw, struct mdss_dsi_ctrl_pdata, dba_work); - if (!ctrl_pdata) { - pr_err("%s: invalid ctrl data\n", __func__); - return; - } - - mdss_dsi_ctrl_init_dba(ctrl_pdata); -} - static int mdss_dsi_event_handler(struct mdss_panel_data *pdata, int event, void *arg) { @@ -2414,11 +2171,6 @@ static int mdss_dsi_event_handler(struct mdss_panel_data *pdata, break; case MDSS_EVENT_FB_REGISTERED: mdss_dsi_debugfs_init(ctrl_pdata); - - ctrl_pdata->fbi = (struct fb_info *)arg; - - queue_delayed_work(ctrl_pdata->workq, &ctrl_pdata->dba_work, - HZ); break; default: pr_debug("%s: unhandled event=%d\n", __func__, event); @@ -2600,7 +2352,8 @@ exit: return dsi_pan_node; } -static struct device_node *mdss_dsi_config_panel(struct platform_device *pdev) +static struct device_node *mdss_dsi_config_panel(struct platform_device *pdev, + int ndx) { struct mdss_dsi_ctrl_pdata *ctrl_pdata = platform_get_drvdata(pdev); char panel_cfg[MDSS_MAX_PANEL_LEN]; @@ -2627,7 +2380,7 @@ static struct device_node *mdss_dsi_config_panel(struct platform_device *pdev) return NULL; } - rc = mdss_dsi_panel_init(dsi_pan_node, ctrl_pdata); + rc = mdss_dsi_panel_init(dsi_pan_node, ctrl_pdata, ndx); if (rc) { pr_err("%s: dsi panel init failed\n", __func__); of_node_put(dsi_pan_node); @@ -2857,7 +2610,7 @@ static int mdss_dsi_ctrl_probe(struct platform_device *pdev) return -EPERM; } - dsi_pan_node = mdss_dsi_config_panel(pdev); + dsi_pan_node = mdss_dsi_config_panel(pdev, index); if (!dsi_pan_node) { pr_err("%s: panel configuration failed\n", __func__); return -EINVAL; @@ -2918,16 +2671,6 @@ static int mdss_dsi_ctrl_probe(struct platform_device *pdev) } disable_irq(gpio_to_irq(ctrl_pdata->disp_te_gpio)); } - - ctrl_pdata->workq = create_workqueue("mdss_dsi_dba"); - if (!ctrl_pdata->workq) { - pr_err("%s: Error creating workqueue\n", __func__); - rc = -EPERM; - goto error_pan_node; - } - - INIT_DELAYED_WORK(&ctrl_pdata->dba_work, mdss_dsi_dba_work); - pr_debug("%s: Dsi Ctrl->%d initialized\n", __func__, index); if (index == 0) @@ -3406,10 +3149,6 @@ static int mdss_dsi_ctrl_remove(struct platform_device *pdev) msm_dss_iounmap(&ctrl_pdata->phy_io); msm_dss_iounmap(&ctrl_pdata->ctrl_io); mdss_dsi_debugfs_cleanup(ctrl_pdata); - - if (ctrl_pdata->workq) - destroy_workqueue(ctrl_pdata->workq); - return 0; } diff --git a/drivers/video/fbdev/msm/mdss_dsi.h b/drivers/video/fbdev/msm/mdss_dsi.h index bf654ce797dc..9568b4fc63d3 100644 --- a/drivers/video/fbdev/msm/mdss_dsi.h +++ b/drivers/video/fbdev/msm/mdss_dsi.h @@ -512,7 +512,6 @@ struct mdss_dsi_ctrl_pdata { struct dsi_err_container err_cont; - bool dfps_status; /* dynamic refresh status */ struct switch_dev sdev; bool hpd_state; bool ds_registered; @@ -622,7 +621,8 @@ void mdss_dsi_get_hw_revision(struct mdss_dsi_ctrl_pdata *ctrl); u32 mdss_dsi_panel_cmd_read(struct mdss_dsi_ctrl_pdata *ctrl, char cmd0, char cmd1, void (*fxn)(int), char *rbuf, int len); int mdss_dsi_panel_init(struct device_node *node, - struct mdss_dsi_ctrl_pdata *ctrl_pdata); + struct mdss_dsi_ctrl_pdata *ctrl_pdata, + int ndx); int mdss_dsi_panel_timing_switch(struct mdss_dsi_ctrl_pdata *ctrl_pdata, struct mdss_panel_timing *timing); diff --git a/drivers/video/fbdev/msm/mdss_dsi_panel.c b/drivers/video/fbdev/msm/mdss_dsi_panel.c index c128aaa0f9a4..3076dcd9ce5a 100644 --- a/drivers/video/fbdev/msm/mdss_dsi_panel.c +++ b/drivers/video/fbdev/msm/mdss_dsi_panel.c @@ -716,6 +716,10 @@ static int mdss_dsi_panel_on(struct mdss_panel_data *pdata) ret = ctrl->dba_ops.video_on( ctrl->dba_data, true, &ctrl->dba_video_cfg, 0); + if (ret) { + pr_err("%s: video on failed for chip %s\n", + __func__, ctrl->dba_info.chip_name); + } } end: @@ -2147,9 +2151,12 @@ static int mdss_dsi_panel_timing_from_dt(struct device_node *np, { u32 tmp; u64 tmp64; - int rc, i, len; + int rc, i, len, num_lanes; const char *data; struct mdss_dsi_ctrl_pdata *ctrl_pdata; + struct mdss_panel_info *pinfo; + + pinfo = &panel_data->panel_info; ctrl_pdata = container_of(panel_data, struct mdss_dsi_ctrl_pdata, panel_data); @@ -2211,6 +2218,35 @@ static int mdss_dsi_panel_timing_from_dt(struct device_node *np, "qcom,mdss-dsi-panel-clockrate", (u32 *)&tmp64); pt->timing.clk_rate = !rc ? tmp64 : 0; + /* Update timing parameter to DBA structure*/ + ctrl_pdata->dba_video_cfg.h_active = + pt->timing.xres; + ctrl_pdata->dba_video_cfg.h_front_porch = + pt->timing.h_front_porch; + ctrl_pdata->dba_video_cfg.h_back_porch = + pt->timing.h_back_porch; + ctrl_pdata->dba_video_cfg.h_pulse_width = + pt->timing.h_pulse_width; + ctrl_pdata->dba_video_cfg.v_active = + pt->timing.yres; + ctrl_pdata->dba_video_cfg.v_front_porch = + pt->timing.v_front_porch; + ctrl_pdata->dba_video_cfg.v_back_porch = + pt->timing.v_back_porch; + ctrl_pdata->dba_video_cfg.v_pulse_width = + pt->timing.v_pulse_width; + + num_lanes = 0; + if (pinfo->mipi.data_lane0) + num_lanes++; + if (pinfo->mipi.data_lane1) + num_lanes++; + if (pinfo->mipi.data_lane2) + num_lanes++; + if (pinfo->mipi.data_lane3) + num_lanes++; + ctrl_pdata->dba_video_cfg.num_of_input_lanes = num_lanes; + data = of_get_property(np, "qcom,mdss-dsi-panel-timings", &len); if ((!data) || (len != 12)) { pr_err("%s:%d, Unable to read Phy timing settings", @@ -2565,8 +2601,121 @@ error: return -EINVAL; } +static inline void mdss_dsi_send_cable_notification( + struct mdss_dsi_ctrl_pdata *ctrl_pdata, int val) +{ + int state = 0; + + if (!ctrl_pdata) { + DEV_ERR("%s: invalid input\n", __func__); + return; + } + state = ctrl_pdata->sdev.state; + + switch_set_state(&ctrl_pdata->sdev, val); + + DEV_INFO("%s: cable state %s %d\n", __func__, + ctrl_pdata->sdev.state == state ? + "is same" : "switched to", + ctrl_pdata->sdev.state); +} + +static void mdss_dsi_dba_cb(void *data, enum msm_dba_callback_event event) +{ + int ret = -EINVAL; + struct mdss_dsi_ctrl_pdata *ctrl_pdata = + (struct mdss_dsi_ctrl_pdata *) data; + + if (!ctrl_pdata) { + pr_err("%s: Invalid data\n", __func__); + return; + } + + switch (event) { + case MSM_DBA_CB_HPD_CONNECT: + ctrl_pdata->hpd_state = true; + + if (ctrl_pdata->dba_ops.get_raw_edid) + ret = ctrl_pdata->dba_ops.get_raw_edid( + ctrl_pdata->dba_data, + sizeof(ctrl_pdata->edid_buf), + ctrl_pdata->edid_buf, 0); + + if (!ret) + hdmi_edid_parser(ctrl_pdata->edid_data); + + mdss_dsi_send_cable_notification(ctrl_pdata, 1); + break; + + case MSM_DBA_CB_HPD_DISCONNECT: + mdss_dsi_send_cable_notification(ctrl_pdata, 0); + ctrl_pdata->hpd_state = false; + break; + + default: + break; + } +} + +static void mdss_dsi_ctrl_init_dba(struct mdss_dsi_ctrl_pdata *ctrl_pdata, + int ndx) +{ + struct hdmi_edid_init_data edid_init_data; + msm_dba_cb dba_cb = mdss_dsi_dba_cb; + + if (!ctrl_pdata) { + pr_err("%s: Invalid ctrl data\n", __func__); + goto end; + } + + snprintf(ctrl_pdata->dba_info.client_name, MSM_DBA_CLIENT_NAME_LEN, + "dsi-%d", ndx); + + strlcpy(ctrl_pdata->dba_info.chip_name, "adv7533", + MSM_DBA_CHIP_NAME_MAX_LEN); + + ctrl_pdata->dba_info.instance_id = ndx; + ctrl_pdata->dba_info.cb = dba_cb; + ctrl_pdata->dba_info.cb_data = ctrl_pdata; + + ctrl_pdata->dba_data = msm_dba_register_client( + &ctrl_pdata->dba_info, + &ctrl_pdata->dba_ops); + + if (IS_ERR_OR_NULL(ctrl_pdata->dba_data)) { + pr_err("%s: ds not configured, %p\n", __func__, + ctrl_pdata->dba_data); + goto end; + } + + ctrl_pdata->sdev.name = ctrl_pdata->dba_info.client_name; + if (switch_dev_register(&ctrl_pdata->sdev) < 0) { + pr_err("%s: DSI switch registration failed\n", + __func__); + goto end; + } + + memset(&edid_init_data, 0x00, sizeof(edid_init_data)); + ctrl_pdata->edid_data = hdmi_edid_init(&edid_init_data); + if (!ctrl_pdata->edid_data) { + pr_err("%s: edid parser init failed\n", __func__); + goto end; + } + + if (ctrl_pdata->dba_ops.power_on) + ctrl_pdata->dba_ops.power_on(ctrl_pdata->dba_data, + true, 0); + + ctrl_pdata->ds_registered = true; + ctrl_pdata->hpd_state = true; + mdss_dsi_send_cable_notification(ctrl_pdata, 1); +end: + return; +} + int mdss_dsi_panel_init(struct device_node *node, - struct mdss_dsi_ctrl_pdata *ctrl_pdata) + struct mdss_dsi_ctrl_pdata *ctrl_pdata, + int ndx) { int rc = 0; static const char *panel_name; @@ -2606,5 +2755,7 @@ int mdss_dsi_panel_init(struct device_node *node, ctrl_pdata->panel_data.set_backlight = mdss_dsi_panel_bl_ctrl; ctrl_pdata->switch_mode = mdss_dsi_panel_switch_mode; + mdss_dsi_ctrl_init_dba(ctrl_pdata, ndx); + return 0; } diff --git a/drivers/video/fbdev/msm/msm_dba/Kconfig b/drivers/video/fbdev/msm/msm_dba/Kconfig index 7725a37ce156..69894cd332a2 100644 --- a/drivers/video/fbdev/msm/msm_dba/Kconfig +++ b/drivers/video/fbdev/msm/msm_dba/Kconfig @@ -21,4 +21,4 @@ config MSM_DBA_ADV7533 ---help--- Support for ADV7533 DSI to HDMI display bridge driver. The driver controls the ADV7533 HW through the I2C interface and configures - the DSi input and HDMI output video format. + the DSI input and HDMI output video format. diff --git a/drivers/video/fbdev/msm/msm_dba/adv7533.c b/drivers/video/fbdev/msm/msm_dba/adv7533.c index b356a5d20285..760772cfd1dd 100644 --- a/drivers/video/fbdev/msm/msm_dba/adv7533.c +++ b/drivers/video/fbdev/msm/msm_dba/adv7533.c @@ -29,6 +29,7 @@ #include "msm_dba_internal.h" #define ADV7533_REG_CHIP_REVISION (0x00) +#define ADV7533_DSI_CEC_I2C_ADDR_REG (0xE1) #define ADV7533_RESET_DELAY (100) #define PINCTRL_STATE_ACTIVE "pmx_adv7533_active" @@ -45,7 +46,7 @@ #define MAX_RW_TRIES (3) enum adv7533_i2c_addr { - ADV7533_MAIN = 0x39, + ADV7533_MAIN = 0x3D, ADV7533_CEC_DSI = 0x3C, }; @@ -60,6 +61,7 @@ struct adv7533_reg_cfg { u8 i2c_addr; u8 reg; u8 val; + int sleep_in_ms; }; struct adv7533_platform_data { @@ -89,98 +91,43 @@ struct adv7533_platform_data { }; static struct adv7533_reg_cfg adv7533_init_setup[] = { - /* power down */ - {ADV7533_MAIN, 0x41, 0x50}, /* HPD override */ - {ADV7533_MAIN, 0xD6, 0x48}, + {ADV7533_MAIN, 0xD6, 0x48, 5}, + /* power down */ + {ADV7533_MAIN, 0x41, 0x50, 5}, /* color space */ - {ADV7533_MAIN, 0x16, 0x20}, + {ADV7533_MAIN, 0x16, 0x20, 0}, /* Fixed */ - {ADV7533_MAIN, 0x9A, 0xE0}, + {ADV7533_MAIN, 0x9A, 0xE0, 0}, /* HDCP */ - {ADV7533_MAIN, 0xBA, 0x70}, + {ADV7533_MAIN, 0xBA, 0x70, 0}, /* Fixed */ - {ADV7533_MAIN, 0xDE, 0x82}, + {ADV7533_MAIN, 0xDE, 0x82, 0}, /* V1P2 */ - {ADV7533_MAIN, 0xE4, 0x40}, + {ADV7533_MAIN, 0xE4, 0x40, 0}, /* Fixed */ - {ADV7533_MAIN, 0xE5, 0x80}, + {ADV7533_MAIN, 0xE5, 0x80, 0}, /* Fixed */ - {ADV7533_CEC_DSI, 0x15, 0xD0}, + {ADV7533_CEC_DSI, 0x15, 0xD0, 0}, /* Fixed */ - {ADV7533_CEC_DSI, 0x17, 0xD0}, + {ADV7533_CEC_DSI, 0x17, 0xD0, 0}, /* Fixed */ - {ADV7533_CEC_DSI, 0x24, 0x20}, + {ADV7533_CEC_DSI, 0x24, 0x20, 0}, /* Fixed */ - {ADV7533_CEC_DSI, 0x57, 0x11}, + {ADV7533_CEC_DSI, 0x57, 0x11, 0}, }; static struct adv7533_reg_cfg adv7533_video_setup[] = { /* power up */ - {ADV7533_MAIN, 0x41, 0x10}, + {ADV7533_MAIN, 0x41, 0x10, 0}, /* hdmi enable */ - {ADV7533_CEC_DSI, 0x03, 0x89}, + {ADV7533_CEC_DSI, 0x03, 0x89, 0}, /* hdmi mode, hdcp */ - {ADV7533_MAIN, 0xAF, 0x06}, + {ADV7533_MAIN, 0xAF, 0x06, 0}, /* color depth */ - {ADV7533_MAIN, 0x4C, 0x04}, + {ADV7533_MAIN, 0x4C, 0x04, 0}, /* down dither */ - {ADV7533_MAIN, 0x49, 0x02}, -}; - -static struct adv7533_reg_cfg tg_cfg_1080p[] = { - /* 4 lanes */ - {ADV7533_CEC_DSI, 0x1C, 0x40}, - /* hsync and vsync active low */ - {ADV7533_MAIN, 0x17, 0x02}, - /* Control for Pixel Clock Divider */ - {ADV7533_CEC_DSI, 0x16, 0x00}, - /* Timing Generator Enable */ - {ADV7533_CEC_DSI, 0x27, 0xCB}, - /* h_width 0x898 2200*/ - {ADV7533_CEC_DSI, 0x28, 0x89}, - {ADV7533_CEC_DSI, 0x29, 0x80}, - /* hsync_width 0x2C 44*/ - {ADV7533_CEC_DSI, 0x2A, 0x02}, - {ADV7533_CEC_DSI, 0x2B, 0xC0}, - /* hfp 0x58 88 */ - {ADV7533_CEC_DSI, 0x2C, 0x05}, - {ADV7533_CEC_DSI, 0x2D, 0x80}, - /* hbp 0x94 148 */ - {ADV7533_CEC_DSI, 0x2E, 0x09}, - {ADV7533_CEC_DSI, 0x2F, 0x40}, - /* v_total 0x465 1125 */ - {ADV7533_CEC_DSI, 0x30, 0x46}, - {ADV7533_CEC_DSI, 0x31, 0x50}, - /* vsync_width 0x05 5*/ - {ADV7533_CEC_DSI, 0x32, 0x00}, - {ADV7533_CEC_DSI, 0x33, 0x50}, - /* vfp 0x04 4 */ - {ADV7533_CEC_DSI, 0x34, 0x00}, - {ADV7533_CEC_DSI, 0x35, 0x40}, - /* vbp 0x24 36 */ - {ADV7533_CEC_DSI, 0x36, 0x02}, - {ADV7533_CEC_DSI, 0x37, 0x40}, - /* Timing Generator Enable */ - {ADV7533_CEC_DSI, 0x27, 0xCB}, - {ADV7533_CEC_DSI, 0x27, 0x8B}, - {ADV7533_CEC_DSI, 0x27, 0xCB}, - /* Reset Internal Timing Generator */ - {ADV7533_MAIN, 0xAF, 0x16}, - /* HDMI Mode Select */ - {ADV7533_CEC_DSI, 0x78, 0x03}, - /* HDMI Output Enable */ - {ADV7533_MAIN, 0x40, 0x80}, - /* GC Packet Enable */ - {ADV7533_MAIN, 0x4C, 0x04}, - /* Colour Depth 24-bit per pixel */ - {ADV7533_MAIN, 0x49, 0x00}, - /* Down Dither Output 8-bit Colour Depth */ - {ADV7533_CEC_DSI, 0x05, 0xC8}, - /* ADI Required Write */ - {ADV7533_CEC_DSI, 0xBE, 0x3D}, - /* Test Pattern Disable (0x55[7] = 0) */ - {ADV7533_CEC_DSI, 0x55, 0x00}, + {ADV7533_MAIN, 0x49, 0x02, 0}, }; static struct adv7533_reg_cfg I2S_cfg[] = { @@ -287,9 +234,119 @@ w_err: if (ret != 0) pr_err("%s: Exiting with ret = %d after %d retries\n", __func__, ret, i); + else + pr_debug("[%s,%d] I2C write(0x%02x) [0x%02x]=0x%02x\n", + __func__, __LINE__, addr, reg, val); return ret; } +static int adv7533_read_reg(struct msm_dba_device_info *dev, u32 reg, u32 *val) +{ + int rc = 0; + u8 byte_val = 0, addr = 0; + struct adv7533_platform_data *pdata = NULL; + + if (!dev) { + pr_err("%s: dev is NULL\n", __func__); + return -EINVAL; + } + pdata = container_of(dev, struct adv7533_platform_data, dev_info); + if (!pdata) { + pr_err("%s: pdata is NULL\n", __func__); + return -EINVAL; + } + + addr = (reg & 0x0100)?(pdata->cec_dsi_i2c_addr):(pdata->main_i2c_addr); + rc = adv7533_read_byte(addr, (reg & 0xff), &byte_val); + if (rc) { + pr_err("%s: read reg=0x%02x failed @ addr=0x%02x\n", + __func__, reg, addr); + } else { + pr_debug("%s: read reg=0x%02x ok value=0x%02x @ addr=0x%02x\n", + __func__, reg, byte_val, addr); + *val = (u32)byte_val; + } + + return rc; +} + +static int adv7533_write_reg(struct msm_dba_device_info *dev, u32 reg, u32 val) +{ + int rc = 0; + u8 addr = 0; + struct adv7533_platform_data *pdata = NULL; + + if (!dev) { + pr_err("%s: dev is NULL\n", __func__); + return -EINVAL; + } + pdata = container_of(dev, struct adv7533_platform_data, dev_info); + if (!pdata) { + pr_err("%s: pdata is NULL\n", __func__); + return -EINVAL; + } + + addr = (reg & 0x0100)?(pdata->cec_dsi_i2c_addr):(pdata->main_i2c_addr); + rc = adv7533_write_byte(addr, (reg & 0xff), val); + if (rc) + pr_err("%s: write reg=0x%02x failed @ addr=0x%02x\n", + __func__, reg, pdata->main_i2c_addr); + else + pr_debug("%s: write reg=0x%02x ok value=0x%02x @ addr=0x%02x\n", + __func__, reg, val, pdata->main_i2c_addr); + + return rc; +} + +static int adv7533_dump_debug_info(struct msm_dba_device_info *dev, u32 flags) +{ + int rc = 0; + u8 byte_val = 0; + u16 addr = 0; + struct adv7533_platform_data *pdata = NULL; + + if (!dev) { + pr_err("%s: dev is NULL\n", __func__); + return -EINVAL; + } + pdata = container_of(dev, struct adv7533_platform_data, dev_info); + if (!pdata) { + pr_err("%s: pdata is NULL\n", __func__); + return -EINVAL; + } + + /* dump main addr*/ + pr_err("========Main I2C=0x%02x Start==========\n", + pdata->main_i2c_addr); + for (addr = 0; addr <= 0xFF; addr++) { + rc = adv7533_read_byte(pdata->main_i2c_addr, + (u8)addr, &byte_val); + if (rc) + pr_err("%s: read reg=0x%02x failed @ addr=0x%02x\n", + __func__, addr, pdata->main_i2c_addr); + else + pr_err("0x%02x -> 0x%02X\n", addr, byte_val); + } + pr_err("========Main I2C=0x%02x End==========\n", + pdata->main_i2c_addr); + /* dump CEC addr*/ + pr_err("=======CEC I2C=0x%02x Start=========\n", + pdata->cec_dsi_i2c_addr); + for (addr = 0; addr <= 0xFF; addr++) { + rc = adv7533_read_byte(pdata->cec_dsi_i2c_addr, + (u8)addr, &byte_val); + if (rc) + pr_err("%s: read reg=0x%02x failed @ addr=0x%02x\n", + __func__, addr, pdata->cec_dsi_i2c_addr); + else + pr_err("0x%02x -> 0x%02X\n", addr, byte_val); + } + pr_err("========CEC I2C=0x%02x End==========\n", + pdata->cec_dsi_i2c_addr); + + return rc; +} + static int adv7533_write_regs(struct adv7533_platform_data *pdata, struct adv7533_reg_cfg *cfg, int size) { @@ -323,6 +380,8 @@ static int adv7533_write_regs(struct adv7533_platform_data *pdata, cfg[i].val, cfg[i].reg); goto w_regs_fail; } + if (cfg[i].sleep_in_ms) + msleep(cfg[i].sleep_in_ms); } w_regs_fail: @@ -332,12 +391,12 @@ w_regs_fail: return ret; } -static int adv7533_read_device_rev(void) +static int adv7533_read_device_rev(struct adv7533_platform_data *pdata) { u8 rev = 0; int ret; - ret = adv7533_read_byte(ADV7533_MAIN, ADV7533_REG_CHIP_REVISION, + ret = adv7533_read_byte(pdata->main_i2c_addr, ADV7533_REG_CHIP_REVISION, &rev); if (!ret) @@ -348,13 +407,39 @@ static int adv7533_read_device_rev(void) return ret; } +static int adv7533_program_i2c_addr(struct adv7533_platform_data *pdata) +{ + u8 i2c_8bits = pdata->cec_dsi_i2c_addr << 1; + int ret = 0; + + if (pdata->cec_dsi_i2c_addr != ADV7533_CEC_DSI) { + ret = adv7533_write_byte(pdata->main_i2c_addr, + ADV7533_DSI_CEC_I2C_ADDR_REG, + i2c_8bits); + + if (ret) + pr_err("%s: write err CEC_ADDR[0x%02x] main_addr=0x%02x\n", + __func__, ADV7533_DSI_CEC_I2C_ADDR_REG, + pdata->main_i2c_addr); + } + + return ret; +} + static int adv7533_parse_dt(struct device *dev, struct adv7533_platform_data *pdata) { struct device_node *np = dev->of_node; - u32 temp_val; + u32 temp_val = 0; int ret = 0; + ret = of_property_read_u32(np, "instance_id", &temp_val); + pr_debug("%s: DT property %s is %X\n", __func__, "instance_id", + temp_val); + if (ret) + goto end; + pdata->dev_info.instance_id = temp_val; + ret = of_property_read_u32(np, "adi,main-addr", &temp_val); pr_debug("%s: DT property %s is %X\n", __func__, "adi,main-addr", temp_val); @@ -433,8 +518,8 @@ static int adv7533_gpio_configure(struct adv7533_platform_data *pdata, if (gpio_is_valid(pdata->irq_gpio)) { ret = gpio_request(pdata->irq_gpio, "adv7533_irq_gpio"); if (ret) { - pr_err("unable to request gpio [%d]\n", - pdata->irq_gpio); + pr_err("%d unable to request gpio [%d] ret=%d\n", + __LINE__, pdata->irq_gpio, ret); goto err_none; } ret = gpio_direction_input(pdata->irq_gpio); @@ -448,35 +533,16 @@ static int adv7533_gpio_configure(struct adv7533_platform_data *pdata, goto err_none; } - if (gpio_is_valid(pdata->hpd_irq_gpio)) { - ret = gpio_request(pdata->hpd_irq_gpio, - "adv7533_hpd_irq_gpio"); - if (ret) { - pr_err("unable to request gpio [%d]\n", - pdata->hpd_irq_gpio); - goto err_irq_gpio; - } - ret = gpio_direction_input(pdata->hpd_irq_gpio); - if (ret) { - pr_err("unable to set dir for gpio[%d]\n", - pdata->hpd_irq_gpio); - goto err_hpd_irq_gpio; - } - } else { - pr_err("hpd irq gpio not provided\n"); - goto err_irq_gpio; - } - if (gpio_is_valid(pdata->switch_gpio)) { ret = gpio_request(pdata->switch_gpio, "adv7533_switch_gpio"); if (ret) { - pr_err("unable to request gpio [%d]\n", - pdata->switch_gpio); + pr_err("%d unable to request gpio [%d] ret=%d\n", + __LINE__, pdata->irq_gpio, ret); goto err_hpd_irq_gpio; } - ret = gpio_direction_output(pdata->switch_gpio, 1); + ret = gpio_direction_output(pdata->switch_gpio, 0); if (ret) { pr_err("unable to set dir for gpio [%d]\n", pdata->switch_gpio); @@ -496,7 +562,7 @@ static int adv7533_gpio_configure(struct adv7533_platform_data *pdata, if (gpio_is_valid(pdata->switch_gpio)) gpio_free(pdata->switch_gpio); - return 0; + goto err_none; } err_switch_gpio: @@ -512,32 +578,8 @@ err_none: return ret; } -static void adv7533_get_cmdline_config(void) -{ - int len = 0; - char *t; - - len = strlen(mdss_mdp_panel); - - if (len <= 0) - return; - - t = strnstr(mdss_mdp_panel, "hdmi", MDSS_MAX_PANEL_LEN); - if (t) - pdata->adv_output = true; - else - pdata->adv_output = false; - - t = strnstr(mdss_mdp_panel, "720", MDSS_MAX_PANEL_LEN); - if (t) - pdata->video_mode = ADV7533_VIDEO_720P; - - t = strnstr(mdss_mdp_panel, "1080", MDSS_MAX_PANEL_LEN); - if (t) - pdata->video_mode = ADV7533_VIDEO_1080P; -} - -u32 adv7533_read_edid(u32 size, char *edid_buf) +u32 adv7533_read_edid(struct adv7533_platform_data *pdata, + u32 size, char *edid_buf) { u32 ret = 0, ndx; u8 edid_addr; @@ -548,7 +590,7 @@ u32 adv7533_read_edid(u32 size, char *edid_buf) pr_debug("%s: size %d\n", __func__, size); - ret = adv7533_read(ADV7533_MAIN, 0x43, &edid_addr, 1); + ret = adv7533_read(pdata->main_i2c_addr, 0x43, &edid_addr, 1); if (ret) { pr_err("%s: Error reading edid addr\n", __func__); goto end; @@ -594,8 +636,8 @@ static void adv7533_intr_work(struct work_struct *work) } /* READ Interrupt registers */ - adv7533_read_byte(ADV7533_MAIN, 0x96, &int_status); - adv7533_read_byte(ADV7533_MAIN, 0x42, &int_state); + adv7533_read_byte(pdata->main_i2c_addr, 0x96, &int_status); + adv7533_read_byte(pdata->main_i2c_addr, 0x42, &int_state); if (int_status & BIT(6)) { if (int_state & BIT(5)) { @@ -623,7 +665,7 @@ static void adv7533_intr_work(struct work_struct *work) if (int_status & BIT(2)) { pr_info("%s: EDID READY\n", __func__); - ret = adv7533_read_edid(sizeof(pdata->edid_buf), + ret = adv7533_read_edid(pdata, sizeof(pdata->edid_buf), pdata->edid_buf); if (ret) pr_err("%s: edid read failed\n", __func__); @@ -714,12 +756,86 @@ static int adv7533_power_on(void *client, bool on, u32 flags) goto end; } - queue_delayed_work(pdata->workq, &pdata->adv7533_intr_work_id, HZ/2); + if (pdata->workq) + queue_delayed_work(pdata->workq, &pdata->adv7533_intr_work_id, + HZ/2); end: return ret; } +static void adv7533_video_timing_setup(struct adv7533_platform_data *pdata, + struct msm_dba_video_cfg *cfg) +{ + u32 h_total, hpw, hfp, hbp; + u32 v_total, vpw, vfp, vbp; + u32 num_lanes; + u8 addr = 0; + + if (!pdata || !cfg) { + pr_err("%s: invalid input\n", __func__); + return; + } + + h_total = cfg->h_active + cfg->h_front_porch + + cfg->h_pulse_width + cfg->h_back_porch; + v_total = cfg->v_active + cfg->v_front_porch + + cfg->v_pulse_width + cfg->v_back_porch; + + hpw = cfg->h_pulse_width; + hfp = cfg->h_front_porch; + hbp = cfg->h_back_porch; + + vpw = cfg->v_pulse_width; + vfp = cfg->v_front_porch; + vbp = cfg->v_back_porch; + addr = pdata->cec_dsi_i2c_addr; + num_lanes = cfg->num_of_input_lanes; + + pr_debug("h_total 0x%x, h_active 0x%x, hfp 0x%d, hpw 0x%x, hbp 0x%x\n", + h_total, cfg->h_active, cfg->h_front_porch, + cfg->h_pulse_width, cfg->h_back_porch); + + pr_debug("v_total 0x%x, v_active 0x%x, vfp 0x%x, vpw 0x%x, vbp 0x%x\n", + v_total, cfg->v_active, cfg->v_front_porch, + cfg->v_pulse_width, cfg->v_back_porch); + + /* lane setup */ + adv7533_write_byte(addr, 0x1C, ((num_lanes & 0xF) << 4)); + + /* h_width */ + adv7533_write_byte(addr, 0x28, ((h_total & 0xFF0) >> 4)); + adv7533_write_byte(addr, 0x29, ((h_total & 0xF) << 4)); + + /* hsync_width */ + adv7533_write_byte(addr, 0x2A, ((hpw & 0xFF0) >> 4)); + adv7533_write_byte(addr, 0x2B, ((hpw & 0xF) << 4)); + + /* hfp */ + adv7533_write_byte(addr, 0x2C, ((hfp & 0xFF0) >> 4)); + adv7533_write_byte(addr, 0x2D, ((hfp & 0xF) << 4)); + + /* hbp */ + adv7533_write_byte(addr, 0x2E, ((hbp & 0xFF0) >> 4)); + adv7533_write_byte(addr, 0x2F, ((hbp & 0xF) << 4)); + + /* v_total */ + adv7533_write_byte(addr, 0x30, ((v_total & 0xFF0) >> 4)); + adv7533_write_byte(addr, 0x31, ((v_total & 0xF) << 4)); + + /* vsync_width */ + adv7533_write_byte(addr, 0x32, ((vpw & 0xFF0) >> 4)); + adv7533_write_byte(addr, 0x33, ((vpw & 0xF) << 4)); + + /* vfp */ + adv7533_write_byte(addr, 0x34, ((vfp & 0xFF0) >> 4)); + adv7533_write_byte(addr, 0x35, ((vfp & 0xF) << 4)); + + /* vbp */ + adv7533_write_byte(addr, 0x36, ((vbp & 0xFF0) >> 4)); + adv7533_write_byte(addr, 0x37, ((vbp & 0xF) << 4)); +} + static int adv7533_video_on(void *client, bool on, struct msm_dba_video_cfg *cfg, u32 flags) { @@ -732,12 +848,7 @@ static int adv7533_video_on(void *client, bool on, goto end; } - ret = adv7533_write_regs(pdata, tg_cfg_1080p, - ARRAY_SIZE(tg_cfg_1080p)); - if (ret) { - pr_err("%s: err config 1080p %d\n", __func__, ret); - goto end; - } + adv7533_video_timing_setup(pdata, cfg); ret = adv7533_write_regs(pdata, adv7533_video_setup, ARRAY_SIZE(adv7533_video_setup)); @@ -812,11 +923,13 @@ static int adv7533_register_dba(struct adv7533_platform_data *pdata) client_ops->video_on = adv7533_video_on; client_ops->get_edid_size = adv7533_get_edid_size; client_ops->get_raw_edid = adv7533_get_raw_edid; + pdata->dev_info.dev_ops.read_reg = adv7533_read_reg; + pdata->dev_info.dev_ops.write_reg = adv7533_write_reg; + pdata->dev_info.dev_ops.dump_debug_info = adv7533_dump_debug_info; strlcpy(pdata->dev_info.chip_name, "adv7533", sizeof(pdata->dev_info.chip_name)); - pdata->dev_info.instance_id = 0; pdata->dev_info.reg_fxn = adv7533_reg_fxn; mutex_init(&pdata->dev_info.dev_mutex); @@ -826,13 +939,20 @@ static int adv7533_register_dba(struct adv7533_platform_data *pdata) return msm_dba_add_probed_device(&pdata->dev_info); } +static void adv7533_unregister_dba(struct adv7533_platform_data *pdata) +{ + if (!pdata) + return; + + msm_dba_remove_probed_device(&pdata->dev_info); +} static int adv7533_probe(struct i2c_client *client_, const struct i2c_device_id *id) { int ret = 0; - client = client_; + client = client_; if (client->dev.of_node) { pdata = devm_kzalloc(&client->dev, sizeof(struct adv7533_platform_data), GFP_KERNEL); @@ -842,42 +962,51 @@ static int adv7533_probe(struct i2c_client *client_, ret = adv7533_parse_dt(&client->dev, pdata); if (ret) { pr_err("%s: Failed to parse DT\n", __func__); - goto p_err; + goto err_dt_parse; } } - ret = adv7533_read_device_rev(); + ret = adv7533_read_device_rev(pdata); if (ret != 0) { pr_err("%s: Failed to read revision\n", __func__); - goto p_err; + goto err_dt_parse; + } + + ret = adv7533_program_i2c_addr(pdata); + if (ret != 0) { + pr_err("%s: Failed to program i2c addr\n", __func__); + goto err_dt_parse; } ret = adv7533_register_dba(pdata); - if (ret) + if (ret) { pr_err("%s: Error registering with DBA %d\n", __func__, ret); + goto err_dba_reg; + } ret = pinctrl_select_state(pdata->ts_pinctrl, pdata->pinctrl_state_active); - if (ret < 0) + if (ret < 0) { pr_err("%s: Failed to select %s pinstate %d\n", __func__, PINCTRL_STATE_ACTIVE, ret); + goto err_dba_reg; + } pdata->adv_output = true; - adv7533_get_cmdline_config(); if (!(pdata->disable_gpios)) { ret = adv7533_gpio_configure(pdata, true); if (ret) { pr_err("%s: Failed to configure GPIOs\n", __func__); - goto p_err; + goto err_gpio_cfg; } if (pdata->adv_output) { gpio_set_value(pdata->switch_gpio, 0); } else { gpio_set_value(pdata->switch_gpio, 1); - goto p_err; + goto err_gpio_cfg; } } @@ -888,7 +1017,7 @@ static int adv7533_probe(struct i2c_client *client_, if (ret) { pr_err("%s: Failed to enable ADV7533 interrupt\n", __func__); - goto p_err; + goto err_irq; } if (pdata->audio) { @@ -896,14 +1025,22 @@ static int adv7533_probe(struct i2c_client *client_, if (ret != 0) { pr_err("%s: I2S configuration fail = %d!\n", __func__, ret); - goto p_err; + goto err_dba_helper; } } + dev_set_drvdata(&client->dev, &pdata->dev_info); + ret = msm_dba_helper_sysfs_init(&client->dev); + if (ret) { + pr_err("%s: sysfs init failed\n", __func__); + goto err_dba_helper; + } + pdata->workq = create_workqueue("adv7533_workq"); if (!pdata->workq) { pr_err("%s: workqueue creation failed.\n", __func__); - return -EPERM; + ret = -EPERM; + goto err_workqueue; } INIT_DELAYED_WORK(&pdata->adv7533_intr_work_id, adv7533_intr_work); @@ -913,8 +1050,17 @@ static int adv7533_probe(struct i2c_client *client_, return 0; -p_err: +err_workqueue: + msm_dba_helper_sysfs_remove(&client->dev); +err_dba_helper: + disable_irq(pdata->irq); + free_irq(pdata->irq, pdata); +err_irq: adv7533_gpio_configure(pdata, false); +err_gpio_cfg: + adv7533_unregister_dba(pdata); +err_dba_reg: +err_dt_parse: devm_kfree(&client->dev, pdata); return ret; } diff --git a/drivers/video/fbdev/msm/msm_dba/msm_dba_debug.c b/drivers/video/fbdev/msm/msm_dba/msm_dba_debug.c index b59dd583b98d..be0f0340ea0f 100644 --- a/drivers/video/fbdev/msm/msm_dba/msm_dba_debug.c +++ b/drivers/video/fbdev/msm/msm_dba/msm_dba_debug.c @@ -26,6 +26,10 @@ static inline struct msm_dba_device_info *to_dba_dev(struct device *dev) { + if (!dev) { + pr_err("%s: dev is NULL\n", __func__); + return NULL; + } return dev_get_drvdata(dev); } @@ -35,6 +39,11 @@ static ssize_t device_name_rda_attr(struct device *dev, { struct msm_dba_device_info *device = to_dba_dev(dev); + if (!device) { + pr_err("%s: device is NULL\n", __func__); + return -EINVAL; + } + return snprintf(buf, PAGE_SIZE, "%s:%d\n", device->chip_name, device->instance_id); } @@ -48,6 +57,11 @@ static ssize_t client_list_rda_attr(struct device *dev, struct list_head *pos = NULL; ssize_t bytes = 0; + if (!device) { + pr_err("%s: device is NULL\n", __func__); + return -EINVAL; + } + mutex_lock(&device->dev_mutex); list_for_each(pos, &device->client_list) { @@ -70,6 +84,11 @@ static ssize_t power_status_rda_attr(struct device *dev, struct list_head *pos = NULL; ssize_t bytes = 0; + if (!device) { + pr_err("%s: device is NULL\n", __func__); + return -EINVAL; + } + mutex_lock(&device->dev_mutex); bytes = snprintf(buf, PAGE_SIZE, "power_status:%d\n", device->power_status); @@ -94,6 +113,11 @@ static ssize_t video_status_rda_attr(struct device *dev, struct list_head *pos = NULL; ssize_t bytes = 0; + if (!device) { + pr_err("%s: device is NULL\n", __func__); + return -EINVAL; + } + mutex_lock(&device->dev_mutex); bytes = snprintf(buf, PAGE_SIZE, "video_status:%d\n", device->video_status); @@ -118,6 +142,11 @@ static ssize_t audio_status_rda_attr(struct device *dev, struct list_head *pos = NULL; ssize_t bytes = 0; + if (!device) { + pr_err("%s: device is NULL\n", __func__); + return -EINVAL; + } + mutex_lock(&device->dev_mutex); bytes = snprintf(buf, PAGE_SIZE, "audio_status:%d\n", device->audio_status); @@ -146,6 +175,11 @@ static ssize_t write_reg_wta_attr(struct device *dev, int rc = 0; int len; + if (!device) { + pr_err("%s: device is NULL\n", __func__); + return -EINVAL; + } + len = strlen(buf); strlcpy(str, buf, 20); if (len < 20) @@ -195,6 +229,11 @@ static ssize_t read_reg_rda_attr(struct device *dev, struct msm_dba_device_info *device = to_dba_dev(dev); ssize_t bytes; + if (!device) { + pr_err("%s: device is NULL\n", __func__); + return -EINVAL; + } + mutex_lock(&device->dev_mutex); bytes = snprintf(buf, PAGE_SIZE, "0x%x\n", device->register_val); @@ -214,6 +253,11 @@ static ssize_t read_reg_wta_attr(struct device *dev, int rc = 0; u32 val = 0; + if (!device) { + pr_err("%s: device is NULL\n", __func__); + return count; + } + rc = kstrtol(buf, 0, ®); if (rc) { pr_err("%s: kstrol error %d\n", __func__, rc); @@ -249,9 +293,18 @@ static ssize_t dump_info_wta_attr(struct device *dev, struct msm_dba_device_info *device = to_dba_dev(dev); int rc; - rc = device->dev_ops.dump_debug_info(device, 0x00); - if (rc) - pr_err("%s: failed to dump debug data\n", __func__); + if (!device) { + pr_err("%s: device is NULL\n", __func__); + return -EINVAL; + } + + if (device->dev_ops.dump_debug_info) { + rc = device->dev_ops.dump_debug_info(device, 0x00); + if (rc) + pr_err("%s: failed to dump debug data\n", __func__); + } else { + pr_err("%s: not supported\n", __func__); + } return count; } @@ -297,3 +350,13 @@ int msm_dba_helper_sysfs_init(struct device *dev) return rc; } + +void msm_dba_helper_sysfs_remove(struct device *dev) +{ + if (!dev) { + pr_err("%s: Invalid params\n", __func__); + return; + } + + sysfs_remove_group(&dev->kobj, &msm_dba_sysfs_attr_grp); +} diff --git a/drivers/video/fbdev/msm/msm_dba/msm_dba_init.c b/drivers/video/fbdev/msm/msm_dba/msm_dba_init.c index 96d0d70bccf8..eebfa03ecb0d 100644 --- a/drivers/video/fbdev/msm/msm_dba/msm_dba_init.c +++ b/drivers/video/fbdev/msm/msm_dba/msm_dba_init.c @@ -53,9 +53,8 @@ int msm_dba_add_probed_device(struct msm_dba_device_info *dev) node->dev = dev; list_add(&node->list, &device_list); - pr_debug("%s: Added new device (%s, %d)", __func__, dev->chip_name, + pr_debug("%s: Added new device (%s, %d)\n", __func__, dev->chip_name, dev->instance_id); - mutex_unlock(&init_mutex); return 0; diff --git a/drivers/video/fbdev/msm/msm_dba/msm_dba_internal.h b/drivers/video/fbdev/msm/msm_dba/msm_dba_internal.h index 5da673bfcffb..594a66c3e68a 100644 --- a/drivers/video/fbdev/msm/msm_dba/msm_dba_internal.h +++ b/drivers/video/fbdev/msm/msm_dba/msm_dba_internal.h @@ -305,6 +305,13 @@ int msm_dba_register_hdcp_monitor(struct msm_dba_device_info *dev, bool enable); */ int msm_dba_helper_sysfs_init(struct device *dev); +/** + * msm_dba_helper_sysfs_remove() - remove sysfs attributes + * @dev: pointer to struct device structure. + * + */ +void msm_dba_helper_sysfs_remove(struct device *dev); + /** * msm_dba_helper_force_reset() - force reset bridge chip * @client: client handle