diff options
Diffstat (limited to 'drivers/video/exynos')
-rw-r--r-- | drivers/video/exynos/Kconfig | 3 | ||||
-rw-r--r-- | drivers/video/exynos/exynos_dp_core.c | 132 | ||||
-rw-r--r-- | drivers/video/exynos/exynos_dp_core.h | 110 | ||||
-rw-r--r-- | drivers/video/exynos/exynos_dp_reg.c | 2 | ||||
-rw-r--r-- | drivers/video/exynos/exynos_mipi_dsi.c | 20 | ||||
-rw-r--r-- | drivers/video/exynos/exynos_mipi_dsi_common.c | 7 |
6 files changed, 163 insertions, 111 deletions
diff --git a/drivers/video/exynos/Kconfig b/drivers/video/exynos/Kconfig index 1b035b2eb6b6..1129d0e9e640 100644 --- a/drivers/video/exynos/Kconfig +++ b/drivers/video/exynos/Kconfig @@ -16,6 +16,7 @@ if EXYNOS_VIDEO config EXYNOS_MIPI_DSI bool "EXYNOS MIPI DSI driver support." depends on ARCH_S5PV210 || ARCH_EXYNOS + select GENERIC_PHY help This enables support for MIPI-DSI device. @@ -29,7 +30,7 @@ config EXYNOS_LCD_S6E8AX0 config EXYNOS_DP bool "EXYNOS DP driver support" - depends on ARCH_EXYNOS + depends on OF && ARCH_EXYNOS default n help This enables support for DP device. diff --git a/drivers/video/exynos/exynos_dp_core.c b/drivers/video/exynos/exynos_dp_core.c index 12bbede3b091..5e1a71580051 100644 --- a/drivers/video/exynos/exynos_dp_core.c +++ b/drivers/video/exynos/exynos_dp_core.c @@ -19,8 +19,7 @@ #include <linux/interrupt.h> #include <linux/delay.h> #include <linux/of.h> - -#include <video/exynos_dp.h> +#include <linux/phy/phy.h> #include "exynos_dp_core.h" @@ -894,26 +893,17 @@ static void exynos_dp_hotplug(struct work_struct *work) dev_err(dp->dev, "unable to config video\n"); } -#ifdef CONFIG_OF -static struct exynos_dp_platdata *exynos_dp_dt_parse_pdata(struct device *dev) +static struct video_info *exynos_dp_dt_parse_pdata(struct device *dev) { struct device_node *dp_node = dev->of_node; - struct exynos_dp_platdata *pd; struct video_info *dp_video_config; - pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL); - if (!pd) { - dev_err(dev, "memory allocation for pdata failed\n"); - return ERR_PTR(-ENOMEM); - } dp_video_config = devm_kzalloc(dev, sizeof(*dp_video_config), GFP_KERNEL); - if (!dp_video_config) { dev_err(dev, "memory allocation for video config failed\n"); return ERR_PTR(-ENOMEM); } - pd->video_info = dp_video_config; dp_video_config->h_sync_polarity = of_property_read_bool(dp_node, "hsync-active-high"); @@ -960,7 +950,7 @@ static struct exynos_dp_platdata *exynos_dp_dt_parse_pdata(struct device *dev) return ERR_PTR(-EINVAL); } - return pd; + return dp_video_config; } static int exynos_dp_dt_parse_phydata(struct exynos_dp_device *dp) @@ -971,8 +961,11 @@ static int exynos_dp_dt_parse_phydata(struct exynos_dp_device *dp) dp_phy_node = of_find_node_by_name(dp_phy_node, "dptx-phy"); if (!dp_phy_node) { - dev_err(dp->dev, "could not find dptx-phy node\n"); - return -ENODEV; + dp->phy = devm_phy_get(dp->dev, "dp"); + if (IS_ERR(dp->phy)) + return PTR_ERR(dp->phy); + else + return 0; } if (of_property_read_u32(dp_phy_node, "reg", &phy_base)) { @@ -1003,48 +996,34 @@ err: static void exynos_dp_phy_init(struct exynos_dp_device *dp) { - u32 reg; - - reg = __raw_readl(dp->phy_addr); - reg |= dp->enable_mask; - __raw_writel(reg, dp->phy_addr); -} - -static void exynos_dp_phy_exit(struct exynos_dp_device *dp) -{ - u32 reg; - - reg = __raw_readl(dp->phy_addr); - reg &= ~(dp->enable_mask); - __raw_writel(reg, dp->phy_addr); -} -#else -static struct exynos_dp_platdata *exynos_dp_dt_parse_pdata(struct device *dev) -{ - return NULL; -} - -static int exynos_dp_dt_parse_phydata(struct exynos_dp_device *dp) -{ - return -EINVAL; -} - -static void exynos_dp_phy_init(struct exynos_dp_device *dp) -{ - return; + if (dp->phy) { + phy_power_on(dp->phy); + } else if (dp->phy_addr) { + u32 reg; + + reg = __raw_readl(dp->phy_addr); + reg |= dp->enable_mask; + __raw_writel(reg, dp->phy_addr); + } } static void exynos_dp_phy_exit(struct exynos_dp_device *dp) { - return; + if (dp->phy) { + phy_power_off(dp->phy); + } else if (dp->phy_addr) { + u32 reg; + + reg = __raw_readl(dp->phy_addr); + reg &= ~(dp->enable_mask); + __raw_writel(reg, dp->phy_addr); + } } -#endif /* CONFIG_OF */ static int exynos_dp_probe(struct platform_device *pdev) { struct resource *res; struct exynos_dp_device *dp; - struct exynos_dp_platdata *pdata; int ret = 0; @@ -1057,21 +1036,13 @@ static int exynos_dp_probe(struct platform_device *pdev) dp->dev = &pdev->dev; - if (pdev->dev.of_node) { - pdata = exynos_dp_dt_parse_pdata(&pdev->dev); - if (IS_ERR(pdata)) - return PTR_ERR(pdata); + dp->video_info = exynos_dp_dt_parse_pdata(&pdev->dev); + if (IS_ERR(dp->video_info)) + return PTR_ERR(dp->video_info); - ret = exynos_dp_dt_parse_phydata(dp); - if (ret) - return ret; - } else { - pdata = pdev->dev.platform_data; - if (!pdata) { - dev_err(&pdev->dev, "no platform data\n"); - return -EINVAL; - } - } + ret = exynos_dp_dt_parse_phydata(dp); + if (ret) + return ret; dp->clock = devm_clk_get(&pdev->dev, "dp"); if (IS_ERR(dp->clock)) { @@ -1095,15 +1066,7 @@ static int exynos_dp_probe(struct platform_device *pdev) INIT_WORK(&dp->hotplug_work, exynos_dp_hotplug); - dp->video_info = pdata->video_info; - - if (pdev->dev.of_node) { - if (dp->phy_addr) - exynos_dp_phy_init(dp); - } else { - if (pdata->phy_init) - pdata->phy_init(); - } + exynos_dp_phy_init(dp); exynos_dp_init_dp(dp); @@ -1121,18 +1084,11 @@ static int exynos_dp_probe(struct platform_device *pdev) static int exynos_dp_remove(struct platform_device *pdev) { - struct exynos_dp_platdata *pdata = pdev->dev.platform_data; struct exynos_dp_device *dp = platform_get_drvdata(pdev); flush_work(&dp->hotplug_work); - if (pdev->dev.of_node) { - if (dp->phy_addr) - exynos_dp_phy_exit(dp); - } else { - if (pdata->phy_exit) - pdata->phy_exit(); - } + exynos_dp_phy_exit(dp); clk_disable_unprepare(dp->clock); @@ -1143,20 +1099,13 @@ static int exynos_dp_remove(struct platform_device *pdev) #ifdef CONFIG_PM_SLEEP static int exynos_dp_suspend(struct device *dev) { - struct exynos_dp_platdata *pdata = dev->platform_data; struct exynos_dp_device *dp = dev_get_drvdata(dev); disable_irq(dp->irq); flush_work(&dp->hotplug_work); - if (dev->of_node) { - if (dp->phy_addr) - exynos_dp_phy_exit(dp); - } else { - if (pdata->phy_exit) - pdata->phy_exit(); - } + exynos_dp_phy_exit(dp); clk_disable_unprepare(dp->clock); @@ -1165,16 +1114,9 @@ static int exynos_dp_suspend(struct device *dev) static int exynos_dp_resume(struct device *dev) { - struct exynos_dp_platdata *pdata = dev->platform_data; struct exynos_dp_device *dp = dev_get_drvdata(dev); - if (dev->of_node) { - if (dp->phy_addr) - exynos_dp_phy_init(dp); - } else { - if (pdata->phy_init) - pdata->phy_init(); - } + exynos_dp_phy_init(dp); clk_prepare_enable(dp->clock); @@ -1203,7 +1145,7 @@ static struct platform_driver exynos_dp_driver = { .name = "exynos-dp", .owner = THIS_MODULE, .pm = &exynos_dp_pm_ops, - .of_match_table = of_match_ptr(exynos_dp_match), + .of_match_table = exynos_dp_match, }, }; diff --git a/drivers/video/exynos/exynos_dp_core.h b/drivers/video/exynos/exynos_dp_core.h index 6c567bbf2fb8..607e36d0c147 100644 --- a/drivers/video/exynos/exynos_dp_core.h +++ b/drivers/video/exynos/exynos_dp_core.h @@ -13,6 +13,99 @@ #ifndef _EXYNOS_DP_CORE_H #define _EXYNOS_DP_CORE_H +#define DP_TIMEOUT_LOOP_COUNT 100 +#define MAX_CR_LOOP 5 +#define MAX_EQ_LOOP 5 + +enum link_rate_type { + LINK_RATE_1_62GBPS = 0x06, + LINK_RATE_2_70GBPS = 0x0a +}; + +enum link_lane_count_type { + LANE_COUNT1 = 1, + LANE_COUNT2 = 2, + LANE_COUNT4 = 4 +}; + +enum link_training_state { + START, + CLOCK_RECOVERY, + EQUALIZER_TRAINING, + FINISHED, + FAILED +}; + +enum voltage_swing_level { + VOLTAGE_LEVEL_0, + VOLTAGE_LEVEL_1, + VOLTAGE_LEVEL_2, + VOLTAGE_LEVEL_3, +}; + +enum pre_emphasis_level { + PRE_EMPHASIS_LEVEL_0, + PRE_EMPHASIS_LEVEL_1, + PRE_EMPHASIS_LEVEL_2, + PRE_EMPHASIS_LEVEL_3, +}; + +enum pattern_set { + PRBS7, + D10_2, + TRAINING_PTN1, + TRAINING_PTN2, + DP_NONE +}; + +enum color_space { + COLOR_RGB, + COLOR_YCBCR422, + COLOR_YCBCR444 +}; + +enum color_depth { + COLOR_6, + COLOR_8, + COLOR_10, + COLOR_12 +}; + +enum color_coefficient { + COLOR_YCBCR601, + COLOR_YCBCR709 +}; + +enum dynamic_range { + VESA, + CEA +}; + +enum pll_status { + PLL_UNLOCKED, + PLL_LOCKED +}; + +enum clock_recovery_m_value_type { + CALCULATED_M, + REGISTER_M +}; + +enum video_timing_recognition_type { + VIDEO_TIMING_FROM_CAPTURE, + VIDEO_TIMING_FROM_REGISTER +}; + +enum analog_power_block { + AUX_BLOCK, + CH0_BLOCK, + CH1_BLOCK, + CH2_BLOCK, + CH3_BLOCK, + ANALOG_TOTAL, + POWER_ALL +}; + enum dp_irq_type { DP_IRQ_TYPE_HP_CABLE_IN, DP_IRQ_TYPE_HP_CABLE_OUT, @@ -20,6 +113,22 @@ enum dp_irq_type { DP_IRQ_TYPE_UNKNOWN, }; +struct video_info { + char *name; + + bool h_sync_polarity; + bool v_sync_polarity; + bool interlaced; + + enum color_space color_space; + enum dynamic_range dynamic_range; + enum color_coefficient ycbcr_coeff; + enum color_depth color_depth; + + enum link_rate_type link_rate; + enum link_lane_count_type lane_count; +}; + struct link_train { int eq_loop; int cr_loop[4]; @@ -42,6 +151,7 @@ struct exynos_dp_device { struct video_info *video_info; struct link_train link_train; struct work_struct hotplug_work; + struct phy *phy; }; /* exynos_dp_reg.c */ diff --git a/drivers/video/exynos/exynos_dp_reg.c b/drivers/video/exynos/exynos_dp_reg.c index 29d9d035c73a..b70da5052ff0 100644 --- a/drivers/video/exynos/exynos_dp_reg.c +++ b/drivers/video/exynos/exynos_dp_reg.c @@ -14,8 +14,6 @@ #include <linux/io.h> #include <linux/delay.h> -#include <video/exynos_dp.h> - #include "exynos_dp_core.h" #include "exynos_dp_reg.h" diff --git a/drivers/video/exynos/exynos_mipi_dsi.c b/drivers/video/exynos/exynos_mipi_dsi.c index 32e540600f99..cee9602f9a7b 100644 --- a/drivers/video/exynos/exynos_mipi_dsi.c +++ b/drivers/video/exynos/exynos_mipi_dsi.c @@ -30,6 +30,7 @@ #include <linux/interrupt.h> #include <linux/kthread.h> #include <linux/notifier.h> +#include <linux/phy/phy.h> #include <linux/regulator/consumer.h> #include <linux/pm_runtime.h> #include <linux/err.h> @@ -140,7 +141,6 @@ static int exynos_mipi_dsi_early_blank_mode(struct mipi_dsim_device *dsim, static int exynos_mipi_dsi_blank_mode(struct mipi_dsim_device *dsim, int power) { - struct platform_device *pdev = to_platform_device(dsim->dev); struct mipi_dsim_lcd_driver *client_drv = dsim->dsim_lcd_drv; struct mipi_dsim_lcd_device *client_dev = dsim->dsim_lcd_dev; @@ -156,8 +156,7 @@ static int exynos_mipi_dsi_blank_mode(struct mipi_dsim_device *dsim, int power) exynos_mipi_regulator_enable(dsim); /* enable MIPI-DSI PHY. */ - if (dsim->pd->phy_enable) - dsim->pd->phy_enable(pdev, true); + phy_power_on(dsim->phy); clk_enable(dsim->clock); @@ -373,6 +372,10 @@ static int exynos_mipi_dsi_probe(struct platform_device *pdev) return ret; } + dsim->phy = devm_phy_get(&pdev->dev, "dsim"); + if (IS_ERR(dsim->phy)) + return PTR_ERR(dsim->phy); + dsim->clock = devm_clk_get(&pdev->dev, "dsim0"); if (IS_ERR(dsim->clock)) { dev_err(&pdev->dev, "failed to get dsim clock source\n"); @@ -439,8 +442,7 @@ static int exynos_mipi_dsi_probe(struct platform_device *pdev) exynos_mipi_regulator_enable(dsim); /* enable MIPI-DSI PHY. */ - if (dsim->pd->phy_enable) - dsim->pd->phy_enable(pdev, true); + phy_power_on(dsim->phy); exynos_mipi_update_cfg(dsim); @@ -504,9 +506,8 @@ static int exynos_mipi_dsi_suspend(struct device *dev) if (client_drv && client_drv->suspend) client_drv->suspend(client_dev); - /* enable MIPI-DSI PHY. */ - if (dsim->pd->phy_enable) - dsim->pd->phy_enable(pdev, false); + /* disable MIPI-DSI PHY. */ + phy_power_off(dsim->phy); clk_disable(dsim->clock); @@ -536,8 +537,7 @@ static int exynos_mipi_dsi_resume(struct device *dev) exynos_mipi_regulator_enable(dsim); /* enable MIPI-DSI PHY. */ - if (dsim->pd->phy_enable) - dsim->pd->phy_enable(pdev, true); + phy_power_on(dsim->phy); clk_enable(dsim->clock); diff --git a/drivers/video/exynos/exynos_mipi_dsi_common.c b/drivers/video/exynos/exynos_mipi_dsi_common.c index 520fc9bd887b..85edabfdef5a 100644 --- a/drivers/video/exynos/exynos_mipi_dsi_common.c +++ b/drivers/video/exynos/exynos_mipi_dsi_common.c @@ -220,7 +220,7 @@ int exynos_mipi_dsi_wr_data(struct mipi_dsim_device *dsim, unsigned int data_id, case MIPI_DSI_DCS_LONG_WRITE: { unsigned int size, payload = 0; - INIT_COMPLETION(dsim_wr_comp); + reinit_completion(&dsim_wr_comp); size = data_size * 4; @@ -356,7 +356,7 @@ int exynos_mipi_dsi_rd_data(struct mipi_dsim_device *dsim, unsigned int data_id, msleep(20); mutex_lock(&dsim->lock); - INIT_COMPLETION(dsim_rd_comp); + reinit_completion(&dsim_rd_comp); exynos_mipi_dsi_rd_tx_header(dsim, MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE, req_size); @@ -376,6 +376,7 @@ int exynos_mipi_dsi_rd_data(struct mipi_dsim_device *dsim, unsigned int data_id, "data id %x is not supported current DSI spec.\n", data_id); + mutex_unlock(&dsim->lock); return -EINVAL; } @@ -667,7 +668,7 @@ int exynos_mipi_dsi_init_dsim(struct mipi_dsim_device *dsim) default: dev_info(dsim->dev, "data lane is invalid.\n"); return -EINVAL; - }; + } exynos_mipi_dsi_sw_reset(dsim); exynos_mipi_dsi_func_reset(dsim); |