diff --git a/drivers/misc/rk628/panel.c b/drivers/misc/rk628/panel.c index 64ed0fa4d136..01635b05d11a 100644 --- a/drivers/misc/rk628/panel.c +++ b/drivers/misc/rk628/panel.c @@ -148,14 +148,14 @@ int rk628_panel_info_get(struct rk628 *rk628, struct device_node *np) return ret; } - panel->enable_gpio = devm_gpiod_get_optional(dev, "panel-enable", GPIOD_OUT_LOW); + panel->enable_gpio = devm_gpiod_get_optional(dev, "panel-enable", GPIOD_ASIS); if (IS_ERR(panel->enable_gpio)) { ret = PTR_ERR(panel->enable_gpio); dev_err(dev, "failed to request panel enable GPIO: %d\n", ret); return ret; } - panel->reset_gpio = devm_gpiod_get_optional(dev, "panel-reset", GPIOD_OUT_LOW); + panel->reset_gpio = devm_gpiod_get_optional(dev, "panel-reset", GPIOD_ASIS); if (IS_ERR(panel->reset_gpio)) { ret = PTR_ERR(panel->reset_gpio); dev_err(dev, "failed to request panel reset GPIO: %d\n", ret); diff --git a/drivers/misc/rk628/rk628.c b/drivers/misc/rk628/rk628.c index 15f0ab40ed41..596026111da7 100644 --- a/drivers/misc/rk628/rk628.c +++ b/drivers/misc/rk628/rk628.c @@ -383,19 +383,19 @@ static const struct regmap_config rk628_regmap_config[RK628_DEV_MAX] = { static void rk628_power_on(struct rk628 *rk628, bool on) { if (!rk628->display_enabled && on) { - gpiod_set_value(rk628->enable_gpio, 1); + gpiod_direction_output(rk628->enable_gpio, 1); usleep_range(10000, 11000); - gpiod_set_value(rk628->reset_gpio, 0); + gpiod_direction_output(rk628->reset_gpio, 0); usleep_range(10000, 11000); - gpiod_set_value(rk628->reset_gpio, 1); + gpiod_direction_output(rk628->reset_gpio, 1); usleep_range(10000, 11000); - gpiod_set_value(rk628->reset_gpio, 0); + gpiod_direction_output(rk628->reset_gpio, 0); usleep_range(10000, 11000); } if (!on) { - gpiod_set_value(rk628->reset_gpio, 1); - gpiod_set_value(rk628->enable_gpio, 0); + gpiod_direction_output(rk628->reset_gpio, 1); + gpiod_direction_output(rk628->enable_gpio, 0); } } @@ -494,6 +494,9 @@ static void rk628_set_hdmirx_irq(struct rk628 *rk628, u32 reg, bool enable) static void rk628_pwr_consumption_init(struct rk628 *rk628) { + if (rk628->display_enabled) + return; + /* set pin as int function to allow output interrupt */ rk628_i2c_write(rk628, GRF_GPIO3AB_SEL_CON, 0x30002000); @@ -1329,6 +1332,32 @@ static void rk628_debugfs_create(struct rk628 *rk628) rk628_hdmitx_create_debugfs_file(rk628); } +static void rk628_loader_protect(struct rk628 *rk628) +{ + u32 enabled; + int ret; + + ret = rk628_i2c_read(rk628, GRF_SCALER_CON0, &enabled); + if (ret || !(enabled & SCL_EN(1))) + return; + + if (rk628_input_is_rgb(rk628) || rk628_input_is_bt1120(rk628)) + rk628->display_enabled = true; + + if (rk628_input_is_hdmi(rk628)) { + if (!rk628_hdmirx_boot_state_init(rk628)) + rk628->display_enabled = true; + } + + if (rk628->display_enabled && rk628->panel && rk628->panel->supply) { + ret = regulator_enable(rk628->panel->supply); + if (ret) + dev_info(rk628->dev, "failed to enable panel power supply\n"); + + dev_info(rk628->dev, "%s:%d show uboot logo\n", __func__, __LINE__); + } +} + static int rk628_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -1373,14 +1402,14 @@ rk628_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) clk_prepare_enable(rk628->soc_24M); rk628->enable_gpio = devm_gpiod_get_optional(dev, "enable", - GPIOD_OUT_LOW); + GPIOD_ASIS); if (IS_ERR(rk628->enable_gpio)) { ret = PTR_ERR(rk628->enable_gpio); dev_err(dev, "failed to request enable GPIO: %d\n", ret); goto err_clk; } - rk628->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); + rk628->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_ASIS); if (IS_ERR(rk628->reset_gpio)) { ret = PTR_ERR(rk628->reset_gpio); dev_err(dev, "failed to request reset GPIO: %d\n", ret); @@ -1395,8 +1424,6 @@ rk628_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) goto err_clk; } - rk628_power_on(rk628, true); - for (i = 0; i < RK628_DEV_MAX; i++) { const struct regmap_config *config = &rk628_regmap_config[i]; @@ -1412,6 +1439,9 @@ rk628_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) } } + rk628_loader_protect(rk628); + rk628_power_on(rk628, true); + ret = rk628_version_info(rk628); if (ret) goto err_clk; @@ -1531,6 +1561,13 @@ static int rk628_i2c_remove(struct i2c_client *client) #endif } +static void rk628_i2c_shutdown(struct i2c_client *client) +{ + struct rk628 *rk628 = i2c_get_clientdata(client); + + rk628_power_on(rk628, false); +} + #ifndef CONFIG_FB #ifdef CONFIG_PM_SLEEP static int rk628_suspend(struct device *dev) @@ -1602,6 +1639,7 @@ static struct i2c_driver rk628_i2c_driver = { .probe = rk628_i2c_probe, .remove = rk628_i2c_remove, .id_table = rk628_i2c_id, + .shutdown = rk628_i2c_shutdown, }; diff --git a/drivers/misc/rk628/rk628_hdmirx.c b/drivers/misc/rk628/rk628_hdmirx.c index 36d34913a096..ffbe063264ec 100644 --- a/drivers/misc/rk628/rk628_hdmirx.c +++ b/drivers/misc/rk628/rk628_hdmirx.c @@ -1120,11 +1120,7 @@ static int rk628_hdmirx_init(struct rk628 *rk628) rk628_i2c_update_bits(rk628, GRF_SYSTEM_CON0, SW_INPUT_MODE_MASK, SW_INPUT_MODE(INPUT_MODE_HDMI)); - rk628_hdmirx_set_edid(rk628); - /* clear avi rcv interrupt */ - rk628_i2c_write(rk628, HDMI_RX_PDEC_ICLR, AVI_RCV_ISTS); - rk628_i2c_update_bits(rk628, GRF_SYSTEM_CON0, SW_I2S_DATA_OEN_MASK, SW_I2S_DATA_OEN(0)); dev_info(rk628->dev, "hdmirx driver version: %s\n", DRIVER_VERSION); INIT_DELAYED_WORK(&hdmirx->delayed_work_audio, rk628_hdmirx_delayed_work_audio); return 0; @@ -1152,6 +1148,27 @@ void rk628_hdmirx_enable_interrupts(struct rk628 *rk628, bool en) dev_dbg(rk628->dev, "%s MD_IEN:%#x\n", __func__, md_ien); } +int rk628_hdmirx_boot_state_init(struct rk628 *rk628) +{ + struct rk628_hdmirx *hdmirx; + + if (!rk628->hdmirx) { + int ret; + + ret = rk628_hdmirx_init(rk628); + if (ret < 0 || !rk628->hdmirx) + return ret; + } + + hdmirx = rk628->hdmirx; + hdmirx->plugin = true; + hdmirx->phy_lock = true; + rk628_hdmirx_get_timing(rk628); + rk628_hdmirx_get_input_format(rk628); + + return 0; +} + int rk628_hdmirx_enable(struct rk628 *rk628) { int ret; @@ -1191,6 +1208,14 @@ int rk628_hdmirx_enable(struct rk628 *rk628) rk628_hdmirx_reset_control_deassert(rk628); usleep_range(20, 40); + rk628_hdmirx_set_edid(rk628); + + /* clear avi rcv interrupt */ + rk628_i2c_write(rk628, HDMI_RX_PDEC_ICLR, AVI_RCV_ISTS); + + rk628_i2c_update_bits(rk628, GRF_SYSTEM_CON0, + SW_I2S_DATA_OEN_MASK, SW_I2S_DATA_OEN(0)); + rk628_hdmirx_ctrl_enable(rk628); ret = rk628_hdmirx_phy_setup(rk628); if (ret < 0) @@ -1280,6 +1305,7 @@ int rk628_hdmirx_detect(struct rk628 *rk628) ret |= HDMIRX_PLUGIN; if (!hdmirx->plugin) ret |= HDMIRX_CHANGED; + if (rk628_hdmirx_status_change(rk628)) ret |= HDMIRX_CHANGED; @@ -1291,6 +1317,7 @@ int rk628_hdmirx_detect(struct rk628 *rk628) if (!hdmirx->phy_lock) ret |= HDMIRX_NOLOCK; + hdmirx->plugin = true; } else { ret |= HDMIRX_PLUGOUT; diff --git a/drivers/misc/rk628/rk628_hdmirx.h b/drivers/misc/rk628/rk628_hdmirx.h index ae159a7d23c4..e80b55356a60 100644 --- a/drivers/misc/rk628/rk628_hdmirx.h +++ b/drivers/misc/rk628/rk628_hdmirx.h @@ -631,6 +631,7 @@ #define HDMIRX_NOSIGNAL BIT(3) #define HDMIRX_NOLOCK BIT(4) +int rk628_hdmirx_boot_state_init(struct rk628 *rk628); void rk628_hdmirx_enable_interrupts(struct rk628 *rk628, bool en); int rk628_hdmirx_enable(struct rk628 *rk628); void rk628_hdmirx_disable(struct rk628 *rk628);