diff options
author | Hans Verkuil <hverkuil@xs4all.nl> | 2016-08-05 10:38:32 -0300 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@s-opensource.com> | 2016-08-24 06:35:52 -0300 |
commit | d0d44516f8e989392d1fa545ae58ea6694743db9 (patch) | |
tree | cc111a2543a5ab598bbf2811e7ea0411da473e22 | |
parent | f304562ed3c97e237a77b3da57b0e43f264bd82a (diff) |
[media] s5p-tv: remove obsolete driver
The s5p-tv driver has been replaced by the exynos drm driver for quite a
long time now. Remove this driver to avoid having duplicate drivers,
of which this one is considered dead code by Samsung.
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Acked-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Acked-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
20 files changed, 1 insertions, 5909 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 6c33d29f79b0..998fd6b767f2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1666,14 +1666,6 @@ S: Maintained F: arch/arm/plat-samsung/s5p-dev-mfc.c F: drivers/media/platform/s5p-mfc/ -ARM/SAMSUNG S5P SERIES TV SUBSYSTEM SUPPORT -M: Kyungmin Park <kyungmin.park@samsung.com> -M: Tomasz Stanislawski <t.stanislaws@samsung.com> -L: linux-arm-kernel@lists.infradead.org -L: linux-media@vger.kernel.org -S: Maintained -F: drivers/media/platform/s5p-tv/ - ARM/SAMSUNG S5P SERIES HDMI CEC SUBSYSTEM SUPPORT M: Kyungmin Park <kyungmin.park@samsung.com> L: linux-arm-kernel@lists.infradead.org diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig index 83f61c513b7e..465d344f3391 100644 --- a/drivers/gpu/drm/exynos/Kconfig +++ b/drivers/gpu/drm/exynos/Kconfig @@ -38,7 +38,6 @@ config DRM_EXYNOS7_DECON config DRM_EXYNOS_MIXER bool "Mixer" - depends on !VIDEO_SAMSUNG_S5P_TV help Choose this option if you want to use Exynos Mixer for DRM. @@ -77,7 +76,7 @@ config DRM_EXYNOS_DP config DRM_EXYNOS_HDMI bool "HDMI" - depends on !VIDEO_SAMSUNG_S5P_TV && (DRM_EXYNOS_MIXER || DRM_EXYNOS5433_DECON) + depends on DRM_EXYNOS_MIXER || DRM_EXYNOS5433_DECON help Choose this option if you want to use Exynos HDMI for DRM. diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig index b23db1779808..7843e8f3d37d 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig @@ -107,7 +107,6 @@ config VIDEO_S3C_CAMIF source "drivers/media/platform/soc_camera/Kconfig" source "drivers/media/platform/exynos4-is/Kconfig" -source "drivers/media/platform/s5p-tv/Kconfig" source "drivers/media/platform/am437x/Kconfig" source "drivers/media/platform/xilinx/Kconfig" source "drivers/media/platform/rcar-vin/Kconfig" diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile index 37b6c75f0b15..536d1d8ef022 100644 --- a/drivers/media/platform/Makefile +++ b/drivers/media/platform/Makefile @@ -30,7 +30,6 @@ obj-$(CONFIG_VIDEO_S3C_CAMIF) += s3c-camif/ obj-$(CONFIG_VIDEO_SAMSUNG_EXYNOS4_IS) += exynos4-is/ obj-$(CONFIG_VIDEO_SAMSUNG_S5P_JPEG) += s5p-jpeg/ obj-$(CONFIG_VIDEO_SAMSUNG_S5P_MFC) += s5p-mfc/ -obj-$(CONFIG_VIDEO_SAMSUNG_S5P_TV) += s5p-tv/ obj-$(CONFIG_VIDEO_SAMSUNG_S5P_G2D) += s5p-g2d/ obj-$(CONFIG_VIDEO_SAMSUNG_EXYNOS_GSC) += exynos-gsc/ diff --git a/drivers/media/platform/s5p-tv/Kconfig b/drivers/media/platform/s5p-tv/Kconfig deleted file mode 100644 index 697aaed42486..000000000000 --- a/drivers/media/platform/s5p-tv/Kconfig +++ /dev/null @@ -1,88 +0,0 @@ -# drivers/media/platform/s5p-tv/Kconfig -# -# Copyright (c) 2010-2011 Samsung Electronics Co., Ltd. -# http://www.samsung.com/ -# Tomasz Stanislawski <t.stanislaws@samsung.com> -# -# Licensed under GPL - -config VIDEO_SAMSUNG_S5P_TV - bool "Samsung TV driver for S5P platform" - depends on PM - depends on ARCH_S5PV210 || ARCH_EXYNOS || COMPILE_TEST - default n - ---help--- - Say Y here to enable selecting the TV output devices for - Samsung S5P platform. - -if VIDEO_SAMSUNG_S5P_TV - -config VIDEO_SAMSUNG_S5P_HDMI - tristate "Samsung HDMI Driver" - depends on VIDEO_V4L2 - depends on I2C - depends on VIDEO_SAMSUNG_S5P_TV - select VIDEO_SAMSUNG_S5P_HDMIPHY - help - Say Y here if you want support for the HDMI output - interface in S5P Samsung SoC. The driver can be compiled - as module. It is an auxiliary driver, that exposes a V4L2 - subdev for use by other drivers. This driver requires - hdmiphy driver to work correctly. - -config VIDEO_SAMSUNG_S5P_HDMI_DEBUG - bool "Enable debug for HDMI Driver" - depends on VIDEO_SAMSUNG_S5P_HDMI - default n - help - Enables debugging for HDMI driver. - -config VIDEO_SAMSUNG_S5P_HDMIPHY - tristate "Samsung HDMIPHY Driver" - depends on VIDEO_DEV && VIDEO_V4L2 && I2C - depends on VIDEO_SAMSUNG_S5P_TV - help - Say Y here if you want support for the physical HDMI - interface in S5P Samsung SoC. The driver can be compiled - as module. It is an I2C driver, that exposes a V4L2 - subdev for use by other drivers. - -config VIDEO_SAMSUNG_S5P_SII9234 - tristate "Samsung SII9234 Driver" - depends on VIDEO_DEV && VIDEO_V4L2 && I2C - depends on VIDEO_SAMSUNG_S5P_TV - help - Say Y here if you want support for the MHL interface - in S5P Samsung SoC. The driver can be compiled - as module. It is an I2C driver, that exposes a V4L2 - subdev for use by other drivers. - -config VIDEO_SAMSUNG_S5P_SDO - tristate "Samsung Analog TV Driver" - depends on VIDEO_DEV && VIDEO_V4L2 - depends on VIDEO_SAMSUNG_S5P_TV - help - Say Y here if you want support for the analog TV output - interface in S5P Samsung SoC. The driver can be compiled - as module. It is an auxiliary driver, that exposes a V4L2 - subdev for use by other drivers. This driver requires - hdmiphy driver to work correctly. - -config VIDEO_SAMSUNG_S5P_MIXER - tristate "Samsung Mixer and Video Processor Driver" - depends on VIDEO_DEV && VIDEO_V4L2 - depends on VIDEO_SAMSUNG_S5P_TV - depends on HAS_DMA - select VIDEOBUF2_DMA_CONTIG - help - Say Y here if you want support for the Mixer in Samsung S5P SoCs. - This device produce image data to one of output interfaces. - -config VIDEO_SAMSUNG_S5P_MIXER_DEBUG - bool "Enable debug for Mixer Driver" - depends on VIDEO_SAMSUNG_S5P_MIXER - default n - help - Enables debugging for Mixer driver. - -endif # VIDEO_SAMSUNG_S5P_TV diff --git a/drivers/media/platform/s5p-tv/Makefile b/drivers/media/platform/s5p-tv/Makefile deleted file mode 100644 index 7cd47902e269..000000000000 --- a/drivers/media/platform/s5p-tv/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -# drivers/media/platform/samsung/tvout/Makefile -# -# Copyright (c) 2010-2011 Samsung Electronics Co., Ltd. -# http://www.samsung.com/ -# Tomasz Stanislawski <t.stanislaws@samsung.com> -# -# Licensed under GPL - -obj-$(CONFIG_VIDEO_SAMSUNG_S5P_HDMIPHY) += s5p-hdmiphy.o -s5p-hdmiphy-y += hdmiphy_drv.o -obj-$(CONFIG_VIDEO_SAMSUNG_S5P_SII9234) += s5p-sii9234.o -s5p-sii9234-y += sii9234_drv.o -obj-$(CONFIG_VIDEO_SAMSUNG_S5P_HDMI) += s5p-hdmi.o -s5p-hdmi-y += hdmi_drv.o -obj-$(CONFIG_VIDEO_SAMSUNG_S5P_SDO) += s5p-sdo.o -s5p-sdo-y += sdo_drv.o -obj-$(CONFIG_VIDEO_SAMSUNG_S5P_MIXER) += s5p-mixer.o -s5p-mixer-y += mixer_drv.o mixer_video.o mixer_reg.o mixer_grp_layer.o mixer_vp_layer.o - diff --git a/drivers/media/platform/s5p-tv/hdmi_drv.c b/drivers/media/platform/s5p-tv/hdmi_drv.c deleted file mode 100644 index e71b13e40f59..000000000000 --- a/drivers/media/platform/s5p-tv/hdmi_drv.c +++ /dev/null @@ -1,1059 +0,0 @@ -/* - * Samsung HDMI interface driver - * - * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd. - * - * Tomasz Stanislawski, <t.stanislaws@samsung.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundiation. either version 2 of the License, - * or (at your option) any later version - */ - -#define pr_fmt(fmt) "s5p-tv (hdmi_drv): " fmt - -#ifdef CONFIG_VIDEO_SAMSUNG_S5P_HDMI_DEBUG -#define DEBUG -#endif - -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/io.h> -#include <linux/i2c.h> -#include <linux/platform_device.h> -#include <media/v4l2-subdev.h> -#include <linux/module.h> -#include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/delay.h> -#include <linux/bug.h> -#include <linux/pm_runtime.h> -#include <linux/clk.h> -#include <linux/regulator/consumer.h> -#include <linux/v4l2-dv-timings.h> - -#include <linux/platform_data/media/s5p_hdmi.h> -#include <media/v4l2-common.h> -#include <media/v4l2-dev.h> -#include <media/v4l2-device.h> -#include <media/v4l2-dv-timings.h> - -#include "regs-hdmi.h" - -MODULE_AUTHOR("Tomasz Stanislawski, <t.stanislaws@samsung.com>"); -MODULE_DESCRIPTION("Samsung HDMI"); -MODULE_LICENSE("GPL"); - -struct hdmi_pulse { - u32 beg; - u32 end; -}; - -struct hdmi_timings { - struct hdmi_pulse hact; - u32 hsyn_pol; /* 0 - high, 1 - low */ - struct hdmi_pulse hsyn; - u32 interlaced; - struct hdmi_pulse vact[2]; - u32 vsyn_pol; /* 0 - high, 1 - low */ - u32 vsyn_off; - struct hdmi_pulse vsyn[2]; -}; - -struct hdmi_resources { - struct clk *hdmi; - struct clk *sclk_hdmi; - struct clk *sclk_pixel; - struct clk *sclk_hdmiphy; - struct clk *hdmiphy; - struct regulator_bulk_data *regul_bulk; - int regul_count; -}; - -struct hdmi_device { - /** base address of HDMI registers */ - void __iomem *regs; - /** HDMI interrupt */ - unsigned int irq; - /** pointer to device parent */ - struct device *dev; - /** subdev generated by HDMI device */ - struct v4l2_subdev sd; - /** V4L2 device structure */ - struct v4l2_device v4l2_dev; - /** subdev of HDMIPHY interface */ - struct v4l2_subdev *phy_sd; - /** subdev of MHL interface */ - struct v4l2_subdev *mhl_sd; - /** configuration of current graphic mode */ - const struct hdmi_timings *cur_conf; - /** flag indicating that timings are dirty */ - int cur_conf_dirty; - /** current timings */ - struct v4l2_dv_timings cur_timings; - /** other resources */ - struct hdmi_resources res; -}; - -static const struct platform_device_id hdmi_driver_types[] = { - { - .name = "s5pv210-hdmi", - }, { - .name = "exynos4-hdmi", - }, { - /* end node */ - } -}; - -static const struct v4l2_subdev_ops hdmi_sd_ops; - -static struct hdmi_device *sd_to_hdmi_dev(struct v4l2_subdev *sd) -{ - return container_of(sd, struct hdmi_device, sd); -} - -static inline -void hdmi_write(struct hdmi_device *hdev, u32 reg_id, u32 value) -{ - writel(value, hdev->regs + reg_id); -} - -static inline -void hdmi_write_mask(struct hdmi_device *hdev, u32 reg_id, u32 value, u32 mask) -{ - u32 old = readl(hdev->regs + reg_id); - value = (value & mask) | (old & ~mask); - writel(value, hdev->regs + reg_id); -} - -static inline -void hdmi_writeb(struct hdmi_device *hdev, u32 reg_id, u8 value) -{ - writeb(value, hdev->regs + reg_id); -} - -static inline -void hdmi_writebn(struct hdmi_device *hdev, u32 reg_id, int n, u32 value) -{ - switch (n) { - default: - writeb(value >> 24, hdev->regs + reg_id + 12); - case 3: - writeb(value >> 16, hdev->regs + reg_id + 8); - case 2: - writeb(value >> 8, hdev->regs + reg_id + 4); - case 1: - writeb(value >> 0, hdev->regs + reg_id + 0); - } -} - -static inline u32 hdmi_read(struct hdmi_device *hdev, u32 reg_id) -{ - return readl(hdev->regs + reg_id); -} - -static irqreturn_t hdmi_irq_handler(int irq, void *dev_data) -{ - struct hdmi_device *hdev = dev_data; - u32 intc_flag; - - (void)irq; - intc_flag = hdmi_read(hdev, HDMI_INTC_FLAG); - /* clearing flags for HPD plug/unplug */ - if (intc_flag & HDMI_INTC_FLAG_HPD_UNPLUG) { - pr_info("unplugged\n"); - hdmi_write_mask(hdev, HDMI_INTC_FLAG, ~0, - HDMI_INTC_FLAG_HPD_UNPLUG); - } - if (intc_flag & HDMI_INTC_FLAG_HPD_PLUG) { - pr_info("plugged\n"); - hdmi_write_mask(hdev, HDMI_INTC_FLAG, ~0, - HDMI_INTC_FLAG_HPD_PLUG); - } - - return IRQ_HANDLED; -} - -static void hdmi_reg_init(struct hdmi_device *hdev) -{ - /* enable HPD interrupts */ - hdmi_write_mask(hdev, HDMI_INTC_CON, ~0, HDMI_INTC_EN_GLOBAL | - HDMI_INTC_EN_HPD_PLUG | HDMI_INTC_EN_HPD_UNPLUG); - /* choose DVI mode */ - hdmi_write_mask(hdev, HDMI_MODE_SEL, - HDMI_MODE_DVI_EN, HDMI_MODE_MASK); - hdmi_write_mask(hdev, HDMI_CON_2, ~0, - HDMI_DVI_PERAMBLE_EN | HDMI_DVI_BAND_EN); - /* disable bluescreen */ - hdmi_write_mask(hdev, HDMI_CON_0, 0, HDMI_BLUE_SCR_EN); - /* choose bluescreen (fecal) color */ - hdmi_writeb(hdev, HDMI_BLUE_SCREEN_0, 0x12); - hdmi_writeb(hdev, HDMI_BLUE_SCREEN_1, 0x34); - hdmi_writeb(hdev, HDMI_BLUE_SCREEN_2, 0x56); -} - -static void hdmi_timing_apply(struct hdmi_device *hdev, - const struct hdmi_timings *t) -{ - /* setting core registers */ - hdmi_writebn(hdev, HDMI_H_BLANK_0, 2, t->hact.beg); - hdmi_writebn(hdev, HDMI_H_SYNC_GEN_0, 3, - (t->hsyn_pol << 20) | (t->hsyn.end << 10) | t->hsyn.beg); - hdmi_writeb(hdev, HDMI_VSYNC_POL, t->vsyn_pol); - hdmi_writebn(hdev, HDMI_V_BLANK_0, 3, - (t->vact[0].beg << 11) | t->vact[0].end); - hdmi_writebn(hdev, HDMI_V_SYNC_GEN_1_0, 3, - (t->vsyn[0].beg << 12) | t->vsyn[0].end); - if (t->interlaced) { - u32 vsyn_trans = t->hsyn.beg + t->vsyn_off; - - hdmi_writeb(hdev, HDMI_INT_PRO_MODE, 1); - hdmi_writebn(hdev, HDMI_H_V_LINE_0, 3, - (t->hact.end << 12) | t->vact[1].end); - hdmi_writebn(hdev, HDMI_V_BLANK_F_0, 3, - (t->vact[1].end << 11) | t->vact[1].beg); - hdmi_writebn(hdev, HDMI_V_SYNC_GEN_2_0, 3, - (t->vsyn[1].beg << 12) | t->vsyn[1].end); - hdmi_writebn(hdev, HDMI_V_SYNC_GEN_3_0, 3, - (vsyn_trans << 12) | vsyn_trans); - } else { - hdmi_writeb(hdev, HDMI_INT_PRO_MODE, 0); - hdmi_writebn(hdev, HDMI_H_V_LINE_0, 3, - (t->hact.end << 12) | t->vact[0].end); - } - - /* Timing generator registers */ - hdmi_writebn(hdev, HDMI_TG_H_FSZ_L, 2, t->hact.end); - hdmi_writebn(hdev, HDMI_TG_HACT_ST_L, 2, t->hact.beg); - hdmi_writebn(hdev, HDMI_TG_HACT_SZ_L, 2, t->hact.end - t->hact.beg); - hdmi_writebn(hdev, HDMI_TG_VSYNC_L, 2, t->vsyn[0].beg); - hdmi_writebn(hdev, HDMI_TG_VACT_ST_L, 2, t->vact[0].beg); - hdmi_writebn(hdev, HDMI_TG_VACT_SZ_L, 2, - t->vact[0].end - t->vact[0].beg); - hdmi_writebn(hdev, HDMI_TG_VSYNC_TOP_HDMI_L, 2, t->vsyn[0].beg); - hdmi_writebn(hdev, HDMI_TG_FIELD_TOP_HDMI_L, 2, t->vsyn[0].beg); - if (t->interlaced) { - hdmi_write_mask(hdev, HDMI_TG_CMD, ~0, HDMI_TG_FIELD_EN); - hdmi_writebn(hdev, HDMI_TG_V_FSZ_L, 2, t->vact[1].end); - hdmi_writebn(hdev, HDMI_TG_VSYNC2_L, 2, t->vsyn[1].beg); - hdmi_writebn(hdev, HDMI_TG_FIELD_CHG_L, 2, t->vact[0].end); - hdmi_writebn(hdev, HDMI_TG_VACT_ST2_L, 2, t->vact[1].beg); - hdmi_writebn(hdev, HDMI_TG_VSYNC_BOT_HDMI_L, 2, t->vsyn[1].beg); - hdmi_writebn(hdev, HDMI_TG_FIELD_BOT_HDMI_L, 2, t->vsyn[1].beg); - } else { - hdmi_write_mask(hdev, HDMI_TG_CMD, 0, HDMI_TG_FIELD_EN); - hdmi_writebn(hdev, HDMI_TG_V_FSZ_L, 2, t->vact[0].end); - } -} - -static int hdmi_conf_apply(struct hdmi_device *hdmi_dev) -{ - struct device *dev = hdmi_dev->dev; - const struct hdmi_timings *conf = hdmi_dev->cur_conf; - int ret; - - dev_dbg(dev, "%s\n", __func__); - - /* skip if conf is already synchronized with HW */ - if (!hdmi_dev->cur_conf_dirty) - return 0; - - /* reset hdmiphy */ - hdmi_write_mask(hdmi_dev, HDMI_PHY_RSTOUT, ~0, HDMI_PHY_SW_RSTOUT); - mdelay(10); - hdmi_write_mask(hdmi_dev, HDMI_PHY_RSTOUT, 0, HDMI_PHY_SW_RSTOUT); - mdelay(10); - - /* configure timings */ - ret = v4l2_subdev_call(hdmi_dev->phy_sd, video, s_dv_timings, - &hdmi_dev->cur_timings); - if (ret) { - dev_err(dev, "failed to set timings\n"); - return ret; - } - - /* resetting HDMI core */ - hdmi_write_mask(hdmi_dev, HDMI_CORE_RSTOUT, 0, HDMI_CORE_SW_RSTOUT); - mdelay(10); - hdmi_write_mask(hdmi_dev, HDMI_CORE_RSTOUT, ~0, HDMI_CORE_SW_RSTOUT); - mdelay(10); - - hdmi_reg_init(hdmi_dev); - - /* setting core registers */ - hdmi_timing_apply(hdmi_dev, conf); - - hdmi_dev->cur_conf_dirty = 0; - - return 0; -} - -static void hdmi_dumpregs(struct hdmi_device *hdev, char *prefix) -{ -#define DUMPREG(reg_id) \ - dev_dbg(hdev->dev, "%s:" #reg_id " = %08x\n", prefix, \ - readl(hdev->regs + reg_id)) - - dev_dbg(hdev->dev, "%s: ---- CONTROL REGISTERS ----\n", prefix); - DUMPREG(HDMI_INTC_FLAG); - DUMPREG(HDMI_INTC_CON); - DUMPREG(HDMI_HPD_STATUS); - DUMPREG(HDMI_PHY_RSTOUT); - DUMPREG(HDMI_PHY_VPLL); - DUMPREG(HDMI_PHY_CMU); - DUMPREG(HDMI_CORE_RSTOUT); - - dev_dbg(hdev->dev, "%s: ---- CORE REGISTERS ----\n", prefix); - DUMPREG(HDMI_CON_0); - DUMPREG(HDMI_CON_1); - DUMPREG(HDMI_CON_2); - DUMPREG(HDMI_SYS_STATUS); - DUMPREG(HDMI_PHY_STATUS); - DUMPREG(HDMI_STATUS_EN); - DUMPREG(HDMI_HPD); - DUMPREG(HDMI_MODE_SEL); - DUMPREG(HDMI_HPD_GEN); - DUMPREG(HDMI_DC_CONTROL); - DUMPREG(HDMI_VIDEO_PATTERN_GEN); - - dev_dbg(hdev->dev, "%s: ---- CORE SYNC REGISTERS ----\n", prefix); - DUMPREG(HDMI_H_BLANK_0); - DUMPREG(HDMI_H_BLANK_1); - DUMPREG(HDMI_V_BLANK_0); - DUMPREG(HDMI_V_BLANK_1); - DUMPREG(HDMI_V_BLANK_2); - DUMPREG(HDMI_H_V_LINE_0); - DUMPREG(HDMI_H_V_LINE_1); - DUMPREG(HDMI_H_V_LINE_2); - DUMPREG(HDMI_VSYNC_POL); - DUMPREG(HDMI_INT_PRO_MODE); - DUMPREG(HDMI_V_BLANK_F_0); - DUMPREG(HDMI_V_BLANK_F_1); - DUMPREG(HDMI_V_BLANK_F_2); - DUMPREG(HDMI_H_SYNC_GEN_0); - DUMPREG(HDMI_H_SYNC_GEN_1); - DUMPREG(HDMI_H_SYNC_GEN_2); - DUMPREG(HDMI_V_SYNC_GEN_1_0); - DUMPREG(HDMI_V_SYNC_GEN_1_1); - DUMPREG(HDMI_V_SYNC_GEN_1_2); - DUMPREG(HDMI_V_SYNC_GEN_2_0); - DUMPREG(HDMI_V_SYNC_GEN_2_1); - DUMPREG(HDMI_V_SYNC_GEN_2_2); - DUMPREG(HDMI_V_SYNC_GEN_3_0); - DUMPREG(HDMI_V_SYNC_GEN_3_1); - DUMPREG(HDMI_V_SYNC_GEN_3_2); - - dev_dbg(hdev->dev, "%s: ---- TG REGISTERS ----\n", prefix); - DUMPREG(HDMI_TG_CMD); - DUMPREG(HDMI_TG_H_FSZ_L); - DUMPREG(HDMI_TG_H_FSZ_H); - DUMPREG(HDMI_TG_HACT_ST_L); - DUMPREG(HDMI_TG_HACT_ST_H); - DUMPREG(HDMI_TG_HACT_SZ_L); - DUMPREG(HDMI_TG_HACT_SZ_H); - DUMPREG(HDMI_TG_V_FSZ_L); - DUMPREG(HDMI_TG_V_FSZ_H); - DUMPREG(HDMI_TG_VSYNC_L); - DUMPREG(HDMI_TG_VSYNC_H); - DUMPREG(HDMI_TG_VSYNC2_L); - DUMPREG(HDMI_TG_VSYNC2_H); - DUMPREG(HDMI_TG_VACT_ST_L); - DUMPREG(HDMI_TG_VACT_ST_H); - DUMPREG(HDMI_TG_VACT_SZ_L); - DUMPREG(HDMI_TG_VACT_SZ_H); - DUMPREG(HDMI_TG_FIELD_CHG_L); - DUMPREG(HDMI_TG_FIELD_CHG_H); - DUMPREG(HDMI_TG_VACT_ST2_L); - DUMPREG(HDMI_TG_VACT_ST2_H); - DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_L); - DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_H); - DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_L); - DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_H); - DUMPREG(HDMI_TG_FIELD_TOP_HDMI_L); - DUMPREG(HDMI_TG_FIELD_TOP_HDMI_H); - DUMPREG(HDMI_TG_FIELD_BOT_HDMI_L); - DUMPREG(HDMI_TG_FIELD_BOT_HDMI_H); -#undef DUMPREG -} - -static const struct hdmi_timings hdmi_timings_480p = { - .hact = { .beg = 138, .end = 858 }, - .hsyn_pol = 1, - .hsyn = { .beg = 16, .end = 16 + 62 }, - .interlaced = 0, - .vact[0] = { .beg = 42 + 3, .end = 522 + 3 }, - .vsyn_pol = 1, - .vsyn[0] = { .beg = 6 + 3, .end = 12 + 3}, -}; - -static const struct hdmi_timings hdmi_timings_576p50 = { - .hact = { .beg = 144, .end = 864 }, - .hsyn_pol = 1, - .hsyn = { .beg = 12, .end = 12 + 64 }, - .interlaced = 0, - .vact[0] = { .beg = 44 + 5, .end = 620 + 5 }, - .vsyn_pol = 1, - .vsyn[0] = { .beg = 0 + 5, .end = 5 + 5}, -}; - -static const struct hdmi_timings hdmi_timings_720p60 = { - .hact = { .beg = 370, .end = 1650 }, - .hsyn_pol = 0, - .hsyn = { .beg = 110, .end = 110 + 40 }, - .interlaced = 0, - .vact[0] = { .beg = 25 + 5, .end = 745 + 5 }, - .vsyn_pol = 0, - .vsyn[0] = { .beg = 0 + 5, .end = 5 + 5}, -}; - -static const struct hdmi_timings hdmi_timings_720p50 = { - .hact = { .beg = 700, .end = 1980 }, - .hsyn_pol = 0, - .hsyn = { .beg = 440, .end = 440 + 40 }, - .interlaced = 0, - .vact[0] = { .beg = 25 + 5, .end = 745 + 5 }, - .vsyn_pol = 0, - .vsyn[0] = { .beg = 0 + 5, .end = 5 + 5}, -}; - -static const struct hdmi_timings hdmi_timings_1080p24 = { - .hact = { .beg = 830, .end = 2750 }, - .hsyn_pol = 0, - .hsyn = { .beg = 638, .end = 638 + 44 }, - .interlaced = 0, - .vact[0] = { .beg = 41 + 4, .end = 1121 + 4 }, - .vsyn_pol = 0, - .vsyn[0] = { .beg = 0 + 4, .end = 5 + 4}, -}; - -static const struct hdmi_timings hdmi_timings_1080p60 = { - .hact = { .beg = 280, .end = 2200 }, - .hsyn_pol = 0, - .hsyn = { .beg = 88, .end = 88 + 44 }, - .interlaced = 0, - .vact[0] = { .beg = 41 + 4, .end = 1121 + 4 }, - .vsyn_pol = 0, - .vsyn[0] = { .beg = 0 + 4, .end = 5 + 4}, -}; - -static const struct hdmi_timings hdmi_timings_1080i60 = { - .hact = { .beg = 280, .end = 2200 }, - .hsyn_pol = 0, - .hsyn = { .beg = 88, .end = 88 + 44 }, - .interlaced = 1, - .vact[0] = { .beg = 20 + 2, .end = 560 + 2 }, - .vact[1] = { .beg = 583 + 2, .end = 1123 + 2 }, - .vsyn_pol = 0, - .vsyn_off = 1100, - .vsyn[0] = { .beg = 0 + 2, .end = 5 + 2}, - .vsyn[1] = { .beg = 562 + 2, .end = 567 + 2}, -}; - -static const struct hdmi_timings hdmi_timings_1080i50 = { - .hact = { .beg = 720, .end = 2640 }, - .hsyn_pol = 0, - .hsyn = { .beg = 528, .end = 528 + 44 }, - .interlaced = 1, - .vact[0] = { .beg = 20 + 2, .end = 560 + 2 }, - .vact[1] = { .beg = 583 + 2, .end = 1123 + 2 }, - .vsyn_pol = 0, - .vsyn_off = 1320, - .vsyn[0] = { .beg = 0 + 2, .end = 5 + 2}, - .vsyn[1] = { .beg = 562 + 2, .end = 567 + 2}, -}; - -static const struct hdmi_timings hdmi_timings_1080p50 = { - .hact = { .beg = 720, .end = 2640 }, - .hsyn_pol = 0, - .hsyn = { .beg = 528, .end = 528 + 44 }, - .interlaced = 0, - .vact[0] = { .beg = 41 + 4, .end = 1121 + 4 }, - .vsyn_pol = 0, - .vsyn[0] = { .beg = 0 + 4, .end = 5 + 4}, -}; - -/* default hdmi_timings index of the timings configured on probe */ -#define HDMI_DEFAULT_TIMINGS_IDX (0) - -static const struct { - bool reduced_fps; - const struct v4l2_dv_timings dv_timings; - const struct hdmi_timings *hdmi_timings; -} hdmi_timings[] = { - { false, V4L2_DV_BT_CEA_720X480P59_94, &hdmi_timings_480p }, - { false, V4L2_DV_BT_CEA_720X576P50, &hdmi_timings_576p50 }, - { false, V4L2_DV_BT_CEA_1280X720P50, &hdmi_timings_720p50 }, - { true, V4L2_DV_BT_CEA_1280X720P60, &hdmi_timings_720p60 }, - { false, V4L2_DV_BT_CEA_1920X1080P24, &hdmi_timings_1080p24 }, - { false, V4L2_DV_BT_CEA_1920X1080P30, &hdmi_timings_1080p60 }, - { false, V4L2_DV_BT_CEA_1920X1080P50, &hdmi_timings_1080p50 }, - { false, V4L2_DV_BT_CEA_1920X1080I50, &hdmi_timings_1080i50 }, - { false, V4L2_DV_BT_CEA_1920X1080I60, &hdmi_timings_1080i60 }, - { false, V4L2_DV_BT_CEA_1920X1080P60, &hdmi_timings_1080p60 }, -}; - -static int hdmi_streamon(struct hdmi_device *hdev) -{ - struct device *dev = hdev->dev; - struct hdmi_resources *res = &hdev->res; - int ret, tries; - - dev_dbg(dev, "%s\n", __func__); - - ret = hdmi_conf_apply(hdev); - if (ret) - return ret; - - ret = v4l2_subdev_call(hdev->phy_sd, video, s_stream, 1); - if (ret) - return ret; - - /* waiting for HDMIPHY's PLL to get to steady state */ - for (tries = 100; tries; --tries) { - u32 val = hdmi_read(hdev, HDMI_PHY_STATUS); - if (val & HDMI_PHY_STATUS_READY) - break; - mdelay(1); - } - /* steady state not achieved */ - if (tries == 0) { - dev_err(dev, "hdmiphy's pll could not reach steady state.\n"); - v4l2_subdev_call(hdev->phy_sd, video, s_stream, 0); - hdmi_dumpregs(hdev, "hdmiphy - s_stream"); - return -EIO; - } - - /* starting MHL */ - ret = v4l2_subdev_call(hdev->mhl_sd, video, s_stream, 1); - if (hdev->mhl_sd && ret) { - v4l2_subdev_call(hdev->phy_sd, video, s_stream, 0); - hdmi_dumpregs(hdev, "mhl - s_stream"); - return -EIO; - } - - /* hdmiphy clock is used for HDMI in streaming mode */ - clk_disable(res->sclk_hdmi); - clk_set_parent(res->sclk_hdmi, res->sclk_hdmiphy); - clk_enable(res->sclk_hdmi); - - /* enable HDMI and timing generator */ - hdmi_write_mask(hdev, HDMI_CON_0, ~0, HDMI_EN); - hdmi_write_mask(hdev, HDMI_TG_CMD, ~0, HDMI_TG_EN); - hdmi_dumpregs(hdev, "streamon"); - return 0; -} - -static int hdmi_streamoff(struct hdmi_device *hdev) -{ - struct device *dev = hdev->dev; - struct hdmi_resources *res = &hdev->res; - - dev_dbg(dev, "%s\n", __func__); - - hdmi_write_mask(hdev, HDMI_CON_0, 0, HDMI_EN); - hdmi_write_mask(hdev, HDMI_TG_CMD, 0, HDMI_TG_EN); - - /* pixel(vpll) clock is used for HDMI in config mode */ - clk_disable(res->sclk_hdmi); - clk_set_parent(res->sclk_hdmi, res->sclk_pixel); - clk_enable(res->sclk_hdmi); - - v4l2_subdev_call(hdev->mhl_sd, video, s_stream, 0); - v4l2_subdev_call(hdev->phy_sd, video, s_stream, 0); - - hdmi_dumpregs(hdev, "streamoff"); - return 0; -} - -static int hdmi_s_stream(struct v4l2_subdev *sd, int enable) -{ - struct hdmi_device *hdev = sd_to_hdmi_dev(sd); - struct device *dev = hdev->dev; - - dev_dbg(dev, "%s(%d)\n", __func__, enable); - if (enable) - return hdmi_streamon(hdev); - return hdmi_streamoff(hdev); -} - -static int hdmi_resource_poweron(struct hdmi_resources *res) -{ - int ret; - - /* turn HDMI power on */ - ret = regulator_bulk_enable(res->regul_count, res->regul_bulk); - if (ret < 0) - return ret; - /* power-on hdmi physical interface */ - clk_enable(res->hdmiphy); - /* use VPP as parent clock; HDMIPHY is not working yet */ - clk_set_parent(res->sclk_hdmi, res->sclk_pixel); - /* turn clocks on */ - clk_enable(res->sclk_hdmi); - - return 0; -} - -static void hdmi_resource_poweroff(struct hdmi_resources *res) -{ - /* turn clocks off */ - clk_disable(res->sclk_hdmi); - /* power-off hdmiphy */ - clk_disable(res->hdmiphy); - /* turn HDMI power off */ - regulator_bulk_disable(res->regul_count, res->regul_bulk); -} - -static int hdmi_s_power(struct v4l2_subdev *sd, int on) -{ - struct hdmi_device *hdev = sd_to_hdmi_dev(sd); - int ret; - - if (on) - ret = pm_runtime_get_sync(hdev->dev); - else - ret = pm_runtime_put_sync(hdev->dev); - /* only values < 0 indicate errors */ - return ret < 0 ? ret : 0; -} - -static int hdmi_s_dv_timings(struct v4l2_subdev *sd, - struct v4l2_dv_timings *timings) -{ - struct hdmi_device *hdev = sd_to_hdmi_dev(sd); - struct device *dev = hdev->dev; - int i; - - for (i = 0; i < ARRAY_SIZE(hdmi_timings); i++) - if (v4l2_match_dv_timings(&hdmi_timings[i].dv_timings, - timings, 0, false)) - break; - if (i == ARRAY_SIZE(hdmi_timings)) { - dev_err(dev, "timings not supported\n"); - return -EINVAL; - } - hdev->cur_conf = hdmi_timings[i].hdmi_timings; - hdev->cur_conf_dirty = 1; - hdev->cur_timings = *timings; - if (!hdmi_timings[i].reduced_fps) - hdev->cur_timings.bt.flags &= ~V4L2_DV_FL_CAN_REDUCE_FPS; - return 0; -} - -static int hdmi_g_dv_timings(struct v4l2_subdev *sd, - struct v4l2_dv_timings *timings) -{ - *timings = sd_to_hdmi_dev(sd)->cur_timings; - return 0; -} - -static int hdmi_get_fmt(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_format *format) -{ - struct v4l2_mbus_framefmt *fmt = &format->format; - struct hdmi_device *hdev = sd_to_hdmi_dev(sd); - const struct hdmi_timings *t = hdev->cur_conf; - - dev_dbg(hdev->dev, "%s\n", __func__); - if (!hdev->cur_conf) - return -EINVAL; - if (format->pad) - return -EINVAL; - - memset(fmt, 0, sizeof(*fmt)); - fmt->width = t->hact.end - t->hact.beg; - fmt->height = t->vact[0].end - t->vact[0].beg; - fmt->code = MEDIA_BUS_FMT_FIXED; /* means RGB888 */ - fmt->colorspace = V4L2_COLORSPACE_SRGB; - if (t->interlaced) { - fmt->field = V4L2_FIELD_INTERLACED; - fmt->height *= 2; - } else { - fmt->field = V4L2_FIELD_NONE; - } - return 0; -} - -static int hdmi_enum_dv_timings(struct v4l2_subdev *sd, - struct v4l2_enum_dv_timings *timings) -{ - if (timings->pad != 0) - return -EINVAL; - if (timings->index >= ARRAY_SIZE(hdmi_timings)) - return -EINVAL; - timings->timings = hdmi_timings[timings->index].dv_timings; - if (!hdmi_timings[timings->index].reduced_fps) - timings->timings.bt.flags &= ~V4L2_DV_FL_CAN_REDUCE_FPS; - return 0; -} - -static int hdmi_dv_timings_cap(struct v4l2_subdev *sd, - struct v4l2_dv_timings_cap *cap) -{ - struct hdmi_device *hdev = sd_to_hdmi_dev(sd); - - if (cap->pad != 0) - return -EINVAL; - - /* Let the phy fill in the pixelclock range */ - v4l2_subdev_call(hdev->phy_sd, pad, dv_timings_cap, cap); - cap->type = V4L2_DV_BT_656_1120; - cap->bt.min_width = 720; - cap->bt.max_width = 1920; - cap->bt.min_height = 480; - cap->bt.max_height = 1080; - cap->bt.standards = V4L2_DV_BT_STD_CEA861; - cap->bt.capabilities = V4L2_DV_BT_CAP_INTERLACED | - V4L2_DV_BT_CAP_PROGRESSIVE; - return 0; -} - -static const struct v4l2_subdev_core_ops hdmi_sd_core_ops = { - .s_power = hdmi_s_power, -}; - -static const struct v4l2_subdev_video_ops hdmi_sd_video_ops = { - .s_dv_timings = hdmi_s_dv_timings, - .g_dv_timings = hdmi_g_dv_timings, - .s_stream = hdmi_s_stream, -}; - -static const struct v4l2_subdev_pad_ops hdmi_sd_pad_ops = { - .enum_dv_timings = hdmi_enum_dv_timings, - .dv_timings_cap = hdmi_dv_timings_cap, - .get_fmt = hdmi_get_fmt, -}; - -static const struct v4l2_subdev_ops hdmi_sd_ops = { - .core = &hdmi_sd_core_ops, - .video = &hdmi_sd_video_ops, - .pad = &hdmi_sd_pad_ops, -}; - -static int hdmi_runtime_suspend(struct device *dev) -{ - struct v4l2_subdev *sd = dev_get_drvdata(dev); - struct hdmi_device *hdev = sd_to_hdmi_dev(sd); - - dev_dbg(dev, "%s\n", __func__); - v4l2_subdev_call(hdev->mhl_sd, core, s_power, 0); - hdmi_resource_poweroff(&hdev->res); - /* flag that device context is lost */ - hdev->cur_conf_dirty = 1; - return 0; -} - -static int hdmi_runtime_resume(struct device *dev) -{ - struct v4l2_subdev *sd = dev_get_drvdata(dev); - struct hdmi_device *hdev = sd_to_hdmi_dev(sd); - int ret; - - dev_dbg(dev, "%s\n", __func__); - - ret = hdmi_resource_poweron(&hdev->res); - if (ret < 0) - return ret; - - /* starting MHL */ - ret = v4l2_subdev_call(hdev->mhl_sd, core, s_power, 1); - if (hdev->mhl_sd && ret) |