diff --git a/drivers/gpu/drm/msm/dba_bridge.c b/drivers/gpu/drm/msm/dba_bridge.c index f933a7f3dcfb..49999ba468e5 100644 --- a/drivers/gpu/drm/msm/dba_bridge.c +++ b/drivers/gpu/drm/msm/dba_bridge.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -205,7 +205,8 @@ static void _dba_bridge_disable(struct drm_bridge *bridge) } if (d_bridge->ops.video_on) { - rc = d_bridge->ops.video_on(d_bridge->dba_ctx, false, NULL, 0); + rc = d_bridge->ops.video_on(d_bridge->dba_ctx, + false, NULL, 0); if (rc) SDE_ERROR("video off failed ret=%d\n", rc); } @@ -213,10 +214,19 @@ static void _dba_bridge_disable(struct drm_bridge *bridge) static void _dba_bridge_post_disable(struct drm_bridge *bridge) { + int rc = 0; + struct dba_bridge *d_bridge = to_dba_bridge(bridge); + if (!bridge) { SDE_ERROR("Invalid params\n"); return; } + + if (d_bridge->ops.power_on) { + rc = d_bridge->ops.power_on(d_bridge->dba_ctx, false, 0); + if (rc) + SDE_ERROR("power off failed ret=%d\n", rc); + } } static void _dba_bridge_mode_set(struct drm_bridge *bridge, diff --git a/drivers/video/fbdev/msm/msm_dba/adv7533.c b/drivers/video/fbdev/msm/msm_dba/adv7533.c index 09632b49d33b..8802b58116fb 100644 --- a/drivers/video/fbdev/msm/msm_dba/adv7533.c +++ b/drivers/video/fbdev/msm/msm_dba/adv7533.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -188,6 +188,17 @@ static struct adv7533_reg_cfg adv7533_video_en[] = { {I2C_ADDR_MAIN, 0x40, 0x80, 0}, }; +static struct adv7533_reg_cfg adv7533_video_disable[] = { + /* Timing Generator Disable */ + {I2C_ADDR_CEC_DSI, 0x27, 0x4B, 0}, + /* SPDIF disable */ + {I2C_ADDR_MAIN, 0x0B, 0x00, 0}, + /* Gate CEC Clock */ + {I2C_ADDR_CEC_DSI, 0x05, 0xF8, 0}, + /* power down */ + {I2C_ADDR_MAIN, 0x41, 0x50, 0}, +}; + static struct adv7533_reg_cfg adv7533_cec_en[] = { /* Fixed, clock gate disable */ {I2C_ADDR_CEC_DSI, 0x05, 0xC8, 0}, @@ -1379,6 +1390,12 @@ static int adv7533_power_on(void *client, bool on, u32 flags) mutex_lock(&pdata->ops_mutex); if (on && !pdata->is_power_on) { + if (gpio_is_valid(pdata->switch_gpio)) { + gpio_set_value(pdata->switch_gpio, + pdata->switch_flags); + msleep(ADV7533_RESET_DELAY); + } + adv7533_write_array(pdata, adv7533_init_setup, sizeof(adv7533_init_setup)); @@ -1394,6 +1411,12 @@ static int adv7533_power_on(void *client, bool on, u32 flags) adv7533_write(pdata, I2C_ADDR_MAIN, 0x41, 0x50); pdata->is_power_on = false; + if (gpio_is_valid(pdata->switch_gpio)) { + gpio_set_value(pdata->switch_gpio, + !pdata->switch_flags); + msleep(ADV7533_RESET_DELAY); + } + ret = 0; adv7533_notify_clients(&pdata->dev_info, MSM_DBA_CB_HPD_DISCONNECT); } @@ -1556,49 +1579,57 @@ static int adv7533_video_on(void *client, bool on, u8 reg_val = 0; struct adv7533 *pdata = adv7533_get_platform_data(client); - if (!pdata || !cfg) { + if (!pdata) { pr_err("%s: invalid platform data\n", __func__); return -EINVAL; + } else if (on && !cfg) { + pr_err("%s: invalid cfg data for power on\n", __func__); + return -EINVAL; } mutex_lock(&pdata->ops_mutex); - /* DSI lane configuration */ - lanes = (cfg->num_of_input_lanes << 4); - adv7533_write(pdata, I2C_ADDR_CEC_DSI, 0x1C, lanes); + if (on) { + /* DSI lane configuration */ + lanes = (cfg->num_of_input_lanes << 4); + adv7533_write(pdata, I2C_ADDR_CEC_DSI, 0x1C, lanes); - adv7533_video_setup(pdata, cfg); + adv7533_video_setup(pdata, cfg); - /* hdmi/dvi mode */ - if (cfg->hdmi_mode) - adv7533_write(pdata, I2C_ADDR_MAIN, 0xAF, 0x06); - else - adv7533_write(pdata, I2C_ADDR_MAIN, 0xAF, 0x04); + /* hdmi/dvi mode */ + if (cfg->hdmi_mode) + adv7533_write(pdata, I2C_ADDR_MAIN, 0xAF, 0x06); + else + adv7533_write(pdata, I2C_ADDR_MAIN, 0xAF, 0x04); - /* set scan info for AVI Infoframe*/ - if (cfg->scaninfo) { - adv7533_read(pdata, I2C_ADDR_MAIN, 0x55, ®_val, 1); - reg_val |= cfg->scaninfo & (BIT(1) | BIT(0)); - adv7533_write(pdata, I2C_ADDR_MAIN, 0x55, reg_val); - } + /* set scan info for AVI Infoframe*/ + if (cfg->scaninfo) { + adv7533_read(pdata, I2C_ADDR_MAIN, 0x55, ®_val, 1); + reg_val |= cfg->scaninfo & (BIT(1) | BIT(0)); + adv7533_write(pdata, I2C_ADDR_MAIN, 0x55, reg_val); + } - /* - * aspect ratio and sync polarity set up. - * Currently adv only supports 16:9 or 4:3 aspect ratio - * configuration. - */ - if (cfg->h_active * 3 - cfg->v_active * 4) { - adv7533_write(pdata, I2C_ADDR_MAIN, 0x17, 0x02); - adv7533_write(pdata, I2C_ADDR_MAIN, 0x56, 0x28); + /* + * aspect ratio and sync polarity set up. + * Currently adv only supports 16:9 or 4:3 aspect ratio + * configuration. + */ + if (cfg->h_active * 3 - cfg->v_active * 4) { + adv7533_write(pdata, I2C_ADDR_MAIN, 0x17, 0x02); + adv7533_write(pdata, I2C_ADDR_MAIN, 0x56, 0x28); + } else { + /* 4:3 aspect ratio */ + adv7533_write(pdata, I2C_ADDR_MAIN, 0x17, 0x00); + adv7533_write(pdata, I2C_ADDR_MAIN, 0x56, 0x18); + } + + adv7533_write_array(pdata, adv7533_video_en, + sizeof(adv7533_video_en)); } else { - /* 4:3 aspect ratio */ - adv7533_write(pdata, I2C_ADDR_MAIN, 0x17, 0x00); - adv7533_write(pdata, I2C_ADDR_MAIN, 0x56, 0x18); + adv7533_write_array(pdata, adv7533_video_disable, + sizeof(adv7533_video_disable)); } - adv7533_write_array(pdata, adv7533_video_en, - sizeof(adv7533_video_en)); - mutex_unlock(&pdata->ops_mutex); return ret; }