14b6cb2b6SLucas Stach // SPDX-License-Identifier: GPL-2.0+ 24b6cb2b6SLucas Stach /* 34b6cb2b6SLucas Stach * i.MX drm driver - Television Encoder (TVEv2) 44b6cb2b6SLucas Stach * 54b6cb2b6SLucas Stach * Copyright (C) 2013 Philipp Zabel, Pengutronix 64b6cb2b6SLucas Stach */ 74b6cb2b6SLucas Stach 84b6cb2b6SLucas Stach #include <linux/clk-provider.h> 94b6cb2b6SLucas Stach #include <linux/clk.h> 104b6cb2b6SLucas Stach #include <linux/component.h> 114b6cb2b6SLucas Stach #include <linux/i2c.h> 124b6cb2b6SLucas Stach #include <linux/module.h> 134b6cb2b6SLucas Stach #include <linux/platform_device.h> 144b6cb2b6SLucas Stach #include <linux/regmap.h> 154b6cb2b6SLucas Stach #include <linux/regulator/consumer.h> 164b6cb2b6SLucas Stach #include <linux/videodev2.h> 174b6cb2b6SLucas Stach 184b6cb2b6SLucas Stach #include <video/imx-ipu-v3.h> 194b6cb2b6SLucas Stach 204b6cb2b6SLucas Stach #include <drm/drm_atomic_helper.h> 214b6cb2b6SLucas Stach #include <drm/drm_edid.h> 224b6cb2b6SLucas Stach #include <drm/drm_managed.h> 234b6cb2b6SLucas Stach #include <drm/drm_probe_helper.h> 244b6cb2b6SLucas Stach #include <drm/drm_simple_kms_helper.h> 254b6cb2b6SLucas Stach 264b6cb2b6SLucas Stach #include "imx-drm.h" 274b6cb2b6SLucas Stach 284b6cb2b6SLucas Stach #define TVE_COM_CONF_REG 0x00 294b6cb2b6SLucas Stach #define TVE_TVDAC0_CONT_REG 0x28 304b6cb2b6SLucas Stach #define TVE_TVDAC1_CONT_REG 0x2c 314b6cb2b6SLucas Stach #define TVE_TVDAC2_CONT_REG 0x30 324b6cb2b6SLucas Stach #define TVE_CD_CONT_REG 0x34 334b6cb2b6SLucas Stach #define TVE_INT_CONT_REG 0x64 344b6cb2b6SLucas Stach #define TVE_STAT_REG 0x68 354b6cb2b6SLucas Stach #define TVE_TST_MODE_REG 0x6c 364b6cb2b6SLucas Stach #define TVE_MV_CONT_REG 0xdc 374b6cb2b6SLucas Stach 384b6cb2b6SLucas Stach /* TVE_COM_CONF_REG */ 394b6cb2b6SLucas Stach #define TVE_SYNC_CH_2_EN BIT(22) 404b6cb2b6SLucas Stach #define TVE_SYNC_CH_1_EN BIT(21) 414b6cb2b6SLucas Stach #define TVE_SYNC_CH_0_EN BIT(20) 424b6cb2b6SLucas Stach #define TVE_TV_OUT_MODE_MASK (0x7 << 12) 434b6cb2b6SLucas Stach #define TVE_TV_OUT_DISABLE (0x0 << 12) 444b6cb2b6SLucas Stach #define TVE_TV_OUT_CVBS_0 (0x1 << 12) 454b6cb2b6SLucas Stach #define TVE_TV_OUT_CVBS_2 (0x2 << 12) 464b6cb2b6SLucas Stach #define TVE_TV_OUT_CVBS_0_2 (0x3 << 12) 474b6cb2b6SLucas Stach #define TVE_TV_OUT_SVIDEO_0_1 (0x4 << 12) 484b6cb2b6SLucas Stach #define TVE_TV_OUT_SVIDEO_0_1_CVBS2_2 (0x5 << 12) 494b6cb2b6SLucas Stach #define TVE_TV_OUT_YPBPR (0x6 << 12) 504b6cb2b6SLucas Stach #define TVE_TV_OUT_RGB (0x7 << 12) 514b6cb2b6SLucas Stach #define TVE_TV_STAND_MASK (0xf << 8) 524b6cb2b6SLucas Stach #define TVE_TV_STAND_HD_1080P30 (0xc << 8) 534b6cb2b6SLucas Stach #define TVE_P2I_CONV_EN BIT(7) 544b6cb2b6SLucas Stach #define TVE_INP_VIDEO_FORM BIT(6) 554b6cb2b6SLucas Stach #define TVE_INP_YCBCR_422 (0x0 << 6) 564b6cb2b6SLucas Stach #define TVE_INP_YCBCR_444 (0x1 << 6) 574b6cb2b6SLucas Stach #define TVE_DATA_SOURCE_MASK (0x3 << 4) 584b6cb2b6SLucas Stach #define TVE_DATA_SOURCE_BUS1 (0x0 << 4) 594b6cb2b6SLucas Stach #define TVE_DATA_SOURCE_BUS2 (0x1 << 4) 604b6cb2b6SLucas Stach #define TVE_DATA_SOURCE_EXT (0x2 << 4) 614b6cb2b6SLucas Stach #define TVE_DATA_SOURCE_TESTGEN (0x3 << 4) 624b6cb2b6SLucas Stach #define TVE_IPU_CLK_EN_OFS 3 634b6cb2b6SLucas Stach #define TVE_IPU_CLK_EN BIT(3) 644b6cb2b6SLucas Stach #define TVE_DAC_SAMP_RATE_OFS 1 654b6cb2b6SLucas Stach #define TVE_DAC_SAMP_RATE_WIDTH 2 664b6cb2b6SLucas Stach #define TVE_DAC_SAMP_RATE_MASK (0x3 << 1) 674b6cb2b6SLucas Stach #define TVE_DAC_FULL_RATE (0x0 << 1) 684b6cb2b6SLucas Stach #define TVE_DAC_DIV2_RATE (0x1 << 1) 694b6cb2b6SLucas Stach #define TVE_DAC_DIV4_RATE (0x2 << 1) 704b6cb2b6SLucas Stach #define TVE_EN BIT(0) 714b6cb2b6SLucas Stach 724b6cb2b6SLucas Stach /* TVE_TVDACx_CONT_REG */ 734b6cb2b6SLucas Stach #define TVE_TVDAC_GAIN_MASK (0x3f << 0) 744b6cb2b6SLucas Stach 754b6cb2b6SLucas Stach /* TVE_CD_CONT_REG */ 764b6cb2b6SLucas Stach #define TVE_CD_CH_2_SM_EN BIT(22) 774b6cb2b6SLucas Stach #define TVE_CD_CH_1_SM_EN BIT(21) 784b6cb2b6SLucas Stach #define TVE_CD_CH_0_SM_EN BIT(20) 794b6cb2b6SLucas Stach #define TVE_CD_CH_2_LM_EN BIT(18) 804b6cb2b6SLucas Stach #define TVE_CD_CH_1_LM_EN BIT(17) 814b6cb2b6SLucas Stach #define TVE_CD_CH_0_LM_EN BIT(16) 824b6cb2b6SLucas Stach #define TVE_CD_CH_2_REF_LVL BIT(10) 834b6cb2b6SLucas Stach #define TVE_CD_CH_1_REF_LVL BIT(9) 844b6cb2b6SLucas Stach #define TVE_CD_CH_0_REF_LVL BIT(8) 854b6cb2b6SLucas Stach #define TVE_CD_EN BIT(0) 864b6cb2b6SLucas Stach 874b6cb2b6SLucas Stach /* TVE_INT_CONT_REG */ 884b6cb2b6SLucas Stach #define TVE_FRAME_END_IEN BIT(13) 894b6cb2b6SLucas Stach #define TVE_CD_MON_END_IEN BIT(2) 904b6cb2b6SLucas Stach #define TVE_CD_SM_IEN BIT(1) 914b6cb2b6SLucas Stach #define TVE_CD_LM_IEN BIT(0) 924b6cb2b6SLucas Stach 934b6cb2b6SLucas Stach /* TVE_TST_MODE_REG */ 944b6cb2b6SLucas Stach #define TVE_TVDAC_TEST_MODE_MASK (0x7 << 0) 954b6cb2b6SLucas Stach 964b6cb2b6SLucas Stach #define IMX_TVE_DAC_VOLTAGE 2750000 974b6cb2b6SLucas Stach 984b6cb2b6SLucas Stach enum { 994b6cb2b6SLucas Stach TVE_MODE_TVOUT, 1004b6cb2b6SLucas Stach TVE_MODE_VGA, 1014b6cb2b6SLucas Stach }; 1024b6cb2b6SLucas Stach 1034b6cb2b6SLucas Stach struct imx_tve_encoder { 1044b6cb2b6SLucas Stach struct drm_connector connector; 1054b6cb2b6SLucas Stach struct drm_encoder encoder; 1064b6cb2b6SLucas Stach struct imx_tve *tve; 1074b6cb2b6SLucas Stach }; 1084b6cb2b6SLucas Stach 1094b6cb2b6SLucas Stach struct imx_tve { 1104b6cb2b6SLucas Stach struct device *dev; 1114b6cb2b6SLucas Stach int mode; 1124b6cb2b6SLucas Stach int di_hsync_pin; 1134b6cb2b6SLucas Stach int di_vsync_pin; 1144b6cb2b6SLucas Stach 1154b6cb2b6SLucas Stach struct regmap *regmap; 1164b6cb2b6SLucas Stach struct regulator *dac_reg; 1174b6cb2b6SLucas Stach struct i2c_adapter *ddc; 1184b6cb2b6SLucas Stach struct clk *clk; 1194b6cb2b6SLucas Stach struct clk *di_sel_clk; 1204b6cb2b6SLucas Stach struct clk_hw clk_hw_di; 1214b6cb2b6SLucas Stach struct clk *di_clk; 1224b6cb2b6SLucas Stach }; 1234b6cb2b6SLucas Stach 1244b6cb2b6SLucas Stach static inline struct imx_tve *con_to_tve(struct drm_connector *c) 1254b6cb2b6SLucas Stach { 1264b6cb2b6SLucas Stach return container_of(c, struct imx_tve_encoder, connector)->tve; 1274b6cb2b6SLucas Stach } 1284b6cb2b6SLucas Stach 1294b6cb2b6SLucas Stach static inline struct imx_tve *enc_to_tve(struct drm_encoder *e) 1304b6cb2b6SLucas Stach { 1314b6cb2b6SLucas Stach return container_of(e, struct imx_tve_encoder, encoder)->tve; 1324b6cb2b6SLucas Stach } 1334b6cb2b6SLucas Stach 1344b6cb2b6SLucas Stach static void tve_enable(struct imx_tve *tve) 1354b6cb2b6SLucas Stach { 1364b6cb2b6SLucas Stach clk_prepare_enable(tve->clk); 1374b6cb2b6SLucas Stach regmap_update_bits(tve->regmap, TVE_COM_CONF_REG, TVE_EN, TVE_EN); 1384b6cb2b6SLucas Stach 1394b6cb2b6SLucas Stach /* clear interrupt status register */ 1404b6cb2b6SLucas Stach regmap_write(tve->regmap, TVE_STAT_REG, 0xffffffff); 1414b6cb2b6SLucas Stach 1424b6cb2b6SLucas Stach /* cable detection irq disabled in VGA mode, enabled in TVOUT mode */ 1434b6cb2b6SLucas Stach if (tve->mode == TVE_MODE_VGA) 1444b6cb2b6SLucas Stach regmap_write(tve->regmap, TVE_INT_CONT_REG, 0); 1454b6cb2b6SLucas Stach else 1464b6cb2b6SLucas Stach regmap_write(tve->regmap, TVE_INT_CONT_REG, 1474b6cb2b6SLucas Stach TVE_CD_SM_IEN | 1484b6cb2b6SLucas Stach TVE_CD_LM_IEN | 1494b6cb2b6SLucas Stach TVE_CD_MON_END_IEN); 1504b6cb2b6SLucas Stach } 1514b6cb2b6SLucas Stach 1524b6cb2b6SLucas Stach static void tve_disable(struct imx_tve *tve) 1534b6cb2b6SLucas Stach { 1544b6cb2b6SLucas Stach regmap_update_bits(tve->regmap, TVE_COM_CONF_REG, TVE_EN, 0); 1554b6cb2b6SLucas Stach clk_disable_unprepare(tve->clk); 1564b6cb2b6SLucas Stach } 1574b6cb2b6SLucas Stach 1584b6cb2b6SLucas Stach static int tve_setup_tvout(struct imx_tve *tve) 1594b6cb2b6SLucas Stach { 1604b6cb2b6SLucas Stach return -ENOTSUPP; 1614b6cb2b6SLucas Stach } 1624b6cb2b6SLucas Stach 1634b6cb2b6SLucas Stach static int tve_setup_vga(struct imx_tve *tve) 1644b6cb2b6SLucas Stach { 1654b6cb2b6SLucas Stach unsigned int mask; 1664b6cb2b6SLucas Stach unsigned int val; 1674b6cb2b6SLucas Stach int ret; 1684b6cb2b6SLucas Stach 1694b6cb2b6SLucas Stach /* set gain to (1 + 10/128) to provide 0.7V peak-to-peak amplitude */ 1704b6cb2b6SLucas Stach ret = regmap_update_bits(tve->regmap, TVE_TVDAC0_CONT_REG, 1714b6cb2b6SLucas Stach TVE_TVDAC_GAIN_MASK, 0x0a); 1724b6cb2b6SLucas Stach if (ret) 1734b6cb2b6SLucas Stach return ret; 1744b6cb2b6SLucas Stach 1754b6cb2b6SLucas Stach ret = regmap_update_bits(tve->regmap, TVE_TVDAC1_CONT_REG, 1764b6cb2b6SLucas Stach TVE_TVDAC_GAIN_MASK, 0x0a); 1774b6cb2b6SLucas Stach if (ret) 1784b6cb2b6SLucas Stach return ret; 1794b6cb2b6SLucas Stach 1804b6cb2b6SLucas Stach ret = regmap_update_bits(tve->regmap, TVE_TVDAC2_CONT_REG, 1814b6cb2b6SLucas Stach TVE_TVDAC_GAIN_MASK, 0x0a); 1824b6cb2b6SLucas Stach if (ret) 1834b6cb2b6SLucas Stach return ret; 1844b6cb2b6SLucas Stach 1854b6cb2b6SLucas Stach /* set configuration register */ 1864b6cb2b6SLucas Stach mask = TVE_DATA_SOURCE_MASK | TVE_INP_VIDEO_FORM; 1874b6cb2b6SLucas Stach val = TVE_DATA_SOURCE_BUS2 | TVE_INP_YCBCR_444; 1884b6cb2b6SLucas Stach mask |= TVE_TV_STAND_MASK | TVE_P2I_CONV_EN; 1894b6cb2b6SLucas Stach val |= TVE_TV_STAND_HD_1080P30 | 0; 1904b6cb2b6SLucas Stach mask |= TVE_TV_OUT_MODE_MASK | TVE_SYNC_CH_0_EN; 1914b6cb2b6SLucas Stach val |= TVE_TV_OUT_RGB | TVE_SYNC_CH_0_EN; 1924b6cb2b6SLucas Stach ret = regmap_update_bits(tve->regmap, TVE_COM_CONF_REG, mask, val); 1934b6cb2b6SLucas Stach if (ret) 1944b6cb2b6SLucas Stach return ret; 1954b6cb2b6SLucas Stach 1964b6cb2b6SLucas Stach /* set test mode (as documented) */ 1974b6cb2b6SLucas Stach return regmap_update_bits(tve->regmap, TVE_TST_MODE_REG, 1984b6cb2b6SLucas Stach TVE_TVDAC_TEST_MODE_MASK, 1); 1994b6cb2b6SLucas Stach } 2004b6cb2b6SLucas Stach 2014b6cb2b6SLucas Stach static int imx_tve_connector_get_modes(struct drm_connector *connector) 2024b6cb2b6SLucas Stach { 2034b6cb2b6SLucas Stach struct imx_tve *tve = con_to_tve(connector); 204*d814fbfcSJani Nikula const struct drm_edid *drm_edid; 205*d814fbfcSJani Nikula int ret; 2064b6cb2b6SLucas Stach 2074b6cb2b6SLucas Stach if (!tve->ddc) 2084b6cb2b6SLucas Stach return 0; 2094b6cb2b6SLucas Stach 210*d814fbfcSJani Nikula drm_edid = drm_edid_read_ddc(connector, tve->ddc); 211*d814fbfcSJani Nikula drm_edid_connector_update(connector, drm_edid); 212*d814fbfcSJani Nikula ret = drm_edid_connector_add_modes(connector); 213*d814fbfcSJani Nikula drm_edid_free(drm_edid); 2144b6cb2b6SLucas Stach 2154b6cb2b6SLucas Stach return ret; 2164b6cb2b6SLucas Stach } 2174b6cb2b6SLucas Stach 2184b6cb2b6SLucas Stach static enum drm_mode_status 2194b6cb2b6SLucas Stach imx_tve_connector_mode_valid(struct drm_connector *connector, 2204b6cb2b6SLucas Stach struct drm_display_mode *mode) 2214b6cb2b6SLucas Stach { 2224b6cb2b6SLucas Stach struct imx_tve *tve = con_to_tve(connector); 2234b6cb2b6SLucas Stach unsigned long rate; 2244b6cb2b6SLucas Stach 2254b6cb2b6SLucas Stach /* pixel clock with 2x oversampling */ 2264b6cb2b6SLucas Stach rate = clk_round_rate(tve->clk, 2000UL * mode->clock) / 2000; 2274b6cb2b6SLucas Stach if (rate == mode->clock) 2284b6cb2b6SLucas Stach return MODE_OK; 2294b6cb2b6SLucas Stach 2304b6cb2b6SLucas Stach /* pixel clock without oversampling */ 2314b6cb2b6SLucas Stach rate = clk_round_rate(tve->clk, 1000UL * mode->clock) / 1000; 2324b6cb2b6SLucas Stach if (rate == mode->clock) 2334b6cb2b6SLucas Stach return MODE_OK; 2344b6cb2b6SLucas Stach 2354b6cb2b6SLucas Stach dev_warn(tve->dev, "ignoring mode %dx%d\n", 2364b6cb2b6SLucas Stach mode->hdisplay, mode->vdisplay); 2374b6cb2b6SLucas Stach 2384b6cb2b6SLucas Stach return MODE_BAD; 2394b6cb2b6SLucas Stach } 2404b6cb2b6SLucas Stach 2414b6cb2b6SLucas Stach static void imx_tve_encoder_mode_set(struct drm_encoder *encoder, 2424b6cb2b6SLucas Stach struct drm_display_mode *orig_mode, 2434b6cb2b6SLucas Stach struct drm_display_mode *mode) 2444b6cb2b6SLucas Stach { 2454b6cb2b6SLucas Stach struct imx_tve *tve = enc_to_tve(encoder); 2464b6cb2b6SLucas Stach unsigned long rounded_rate; 2474b6cb2b6SLucas Stach unsigned long rate; 2484b6cb2b6SLucas Stach int div = 1; 2494b6cb2b6SLucas Stach int ret; 2504b6cb2b6SLucas Stach 2514b6cb2b6SLucas Stach /* 2524b6cb2b6SLucas Stach * FIXME 2534b6cb2b6SLucas Stach * we should try 4k * mode->clock first, 2544b6cb2b6SLucas Stach * and enable 4x oversampling for lower resolutions 2554b6cb2b6SLucas Stach */ 2564b6cb2b6SLucas Stach rate = 2000UL * mode->clock; 2574b6cb2b6SLucas Stach clk_set_rate(tve->clk, rate); 2584b6cb2b6SLucas Stach rounded_rate = clk_get_rate(tve->clk); 2594b6cb2b6SLucas Stach if (rounded_rate >= rate) 2604b6cb2b6SLucas Stach div = 2; 2614b6cb2b6SLucas Stach clk_set_rate(tve->di_clk, rounded_rate / div); 2624b6cb2b6SLucas Stach 2634b6cb2b6SLucas Stach ret = clk_set_parent(tve->di_sel_clk, tve->di_clk); 2644b6cb2b6SLucas Stach if (ret < 0) { 2654b6cb2b6SLucas Stach dev_err(tve->dev, "failed to set di_sel parent to tve_di: %d\n", 2664b6cb2b6SLucas Stach ret); 2674b6cb2b6SLucas Stach } 2684b6cb2b6SLucas Stach 2694b6cb2b6SLucas Stach regmap_update_bits(tve->regmap, TVE_COM_CONF_REG, 2704b6cb2b6SLucas Stach TVE_IPU_CLK_EN, TVE_IPU_CLK_EN); 2714b6cb2b6SLucas Stach 2724b6cb2b6SLucas Stach if (tve->mode == TVE_MODE_VGA) 2734b6cb2b6SLucas Stach ret = tve_setup_vga(tve); 2744b6cb2b6SLucas Stach else 2754b6cb2b6SLucas Stach ret = tve_setup_tvout(tve); 2764b6cb2b6SLucas Stach if (ret) 2774b6cb2b6SLucas Stach dev_err(tve->dev, "failed to set configuration: %d\n", ret); 2784b6cb2b6SLucas Stach } 2794b6cb2b6SLucas Stach 2804b6cb2b6SLucas Stach static void imx_tve_encoder_enable(struct drm_encoder *encoder) 2814b6cb2b6SLucas Stach { 2824b6cb2b6SLucas Stach struct imx_tve *tve = enc_to_tve(encoder); 2834b6cb2b6SLucas Stach 2844b6cb2b6SLucas Stach tve_enable(tve); 2854b6cb2b6SLucas Stach } 2864b6cb2b6SLucas Stach 2874b6cb2b6SLucas Stach static void imx_tve_encoder_disable(struct drm_encoder *encoder) 2884b6cb2b6SLucas Stach { 2894b6cb2b6SLucas Stach struct imx_tve *tve = enc_to_tve(encoder); 2904b6cb2b6SLucas Stach 2914b6cb2b6SLucas Stach tve_disable(tve); 2924b6cb2b6SLucas Stach } 2934b6cb2b6SLucas Stach 2944b6cb2b6SLucas Stach static int imx_tve_atomic_check(struct drm_encoder *encoder, 2954b6cb2b6SLucas Stach struct drm_crtc_state *crtc_state, 2964b6cb2b6SLucas Stach struct drm_connector_state *conn_state) 2974b6cb2b6SLucas Stach { 2984b6cb2b6SLucas Stach struct imx_crtc_state *imx_crtc_state = to_imx_crtc_state(crtc_state); 2994b6cb2b6SLucas Stach struct imx_tve *tve = enc_to_tve(encoder); 3004b6cb2b6SLucas Stach 3014b6cb2b6SLucas Stach imx_crtc_state->bus_format = MEDIA_BUS_FMT_GBR888_1X24; 3024b6cb2b6SLucas Stach imx_crtc_state->di_hsync_pin = tve->di_hsync_pin; 3034b6cb2b6SLucas Stach imx_crtc_state->di_vsync_pin = tve->di_vsync_pin; 3044b6cb2b6SLucas Stach 3054b6cb2b6SLucas Stach return 0; 3064b6cb2b6SLucas Stach } 3074b6cb2b6SLucas Stach 3084b6cb2b6SLucas Stach static const struct drm_connector_funcs imx_tve_connector_funcs = { 3094b6cb2b6SLucas Stach .fill_modes = drm_helper_probe_single_connector_modes, 3104b6cb2b6SLucas Stach .destroy = imx_drm_connector_destroy, 3114b6cb2b6SLucas Stach .reset = drm_atomic_helper_connector_reset, 3124b6cb2b6SLucas Stach .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, 3134b6cb2b6SLucas Stach .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, 3144b6cb2b6SLucas Stach }; 3154b6cb2b6SLucas Stach 3164b6cb2b6SLucas Stach static const struct drm_connector_helper_funcs imx_tve_connector_helper_funcs = { 3174b6cb2b6SLucas Stach .get_modes = imx_tve_connector_get_modes, 3184b6cb2b6SLucas Stach .mode_valid = imx_tve_connector_mode_valid, 3194b6cb2b6SLucas Stach }; 3204b6cb2b6SLucas Stach 3214b6cb2b6SLucas Stach static const struct drm_encoder_helper_funcs imx_tve_encoder_helper_funcs = { 3224b6cb2b6SLucas Stach .mode_set = imx_tve_encoder_mode_set, 3234b6cb2b6SLucas Stach .enable = imx_tve_encoder_enable, 3244b6cb2b6SLucas Stach .disable = imx_tve_encoder_disable, 3254b6cb2b6SLucas Stach .atomic_check = imx_tve_atomic_check, 3264b6cb2b6SLucas Stach }; 3274b6cb2b6SLucas Stach 3284b6cb2b6SLucas Stach static irqreturn_t imx_tve_irq_handler(int irq, void *data) 3294b6cb2b6SLucas Stach { 3304b6cb2b6SLucas Stach struct imx_tve *tve = data; 3314b6cb2b6SLucas Stach unsigned int val; 3324b6cb2b6SLucas Stach 3334b6cb2b6SLucas Stach regmap_read(tve->regmap, TVE_STAT_REG, &val); 3344b6cb2b6SLucas Stach 3354b6cb2b6SLucas Stach /* clear interrupt status register */ 3364b6cb2b6SLucas Stach regmap_write(tve->regmap, TVE_STAT_REG, 0xffffffff); 3374b6cb2b6SLucas Stach 3384b6cb2b6SLucas Stach return IRQ_HANDLED; 3394b6cb2b6SLucas Stach } 3404b6cb2b6SLucas Stach 3414b6cb2b6SLucas Stach static unsigned long clk_tve_di_recalc_rate(struct clk_hw *hw, 3424b6cb2b6SLucas Stach unsigned long parent_rate) 3434b6cb2b6SLucas Stach { 3444b6cb2b6SLucas Stach struct imx_tve *tve = container_of(hw, struct imx_tve, clk_hw_di); 3454b6cb2b6SLucas Stach unsigned int val; 3464b6cb2b6SLucas Stach int ret; 3474b6cb2b6SLucas Stach 3484b6cb2b6SLucas Stach ret = regmap_read(tve->regmap, TVE_COM_CONF_REG, &val); 3494b6cb2b6SLucas Stach if (ret < 0) 3504b6cb2b6SLucas Stach return 0; 3514b6cb2b6SLucas Stach 3524b6cb2b6SLucas Stach switch (val & TVE_DAC_SAMP_RATE_MASK) { 3534b6cb2b6SLucas Stach case TVE_DAC_DIV4_RATE: 3544b6cb2b6SLucas Stach return parent_rate / 4; 3554b6cb2b6SLucas Stach case TVE_DAC_DIV2_RATE: 3564b6cb2b6SLucas Stach return parent_rate / 2; 3574b6cb2b6SLucas Stach case TVE_DAC_FULL_RATE: 3584b6cb2b6SLucas Stach default: 3594b6cb2b6SLucas Stach return parent_rate; 3604b6cb2b6SLucas Stach } 3614b6cb2b6SLucas Stach 3624b6cb2b6SLucas Stach return 0; 3634b6cb2b6SLucas Stach } 3644b6cb2b6SLucas Stach 3654b6cb2b6SLucas Stach static long clk_tve_di_round_rate(struct clk_hw *hw, unsigned long rate, 3664b6cb2b6SLucas Stach unsigned long *prate) 3674b6cb2b6SLucas Stach { 3684b6cb2b6SLucas Stach unsigned long div; 3694b6cb2b6SLucas Stach 3704b6cb2b6SLucas Stach div = *prate / rate; 3714b6cb2b6SLucas Stach if (div >= 4) 3724b6cb2b6SLucas Stach return *prate / 4; 3734b6cb2b6SLucas Stach else if (div >= 2) 3744b6cb2b6SLucas Stach return *prate / 2; 3754b6cb2b6SLucas Stach return *prate; 3764b6cb2b6SLucas Stach } 3774b6cb2b6SLucas Stach 3784b6cb2b6SLucas Stach static int clk_tve_di_set_rate(struct clk_hw *hw, unsigned long rate, 3794b6cb2b6SLucas Stach unsigned long parent_rate) 3804b6cb2b6SLucas Stach { 3814b6cb2b6SLucas Stach struct imx_tve *tve = container_of(hw, struct imx_tve, clk_hw_di); 3824b6cb2b6SLucas Stach unsigned long div; 3834b6cb2b6SLucas Stach u32 val; 3844b6cb2b6SLucas Stach int ret; 3854b6cb2b6SLucas Stach 3864b6cb2b6SLucas Stach div = parent_rate / rate; 3874b6cb2b6SLucas Stach if (div >= 4) 3884b6cb2b6SLucas Stach val = TVE_DAC_DIV4_RATE; 3894b6cb2b6SLucas Stach else if (div >= 2) 3904b6cb2b6SLucas Stach val = TVE_DAC_DIV2_RATE; 3914b6cb2b6SLucas Stach else 3924b6cb2b6SLucas Stach val = TVE_DAC_FULL_RATE; 3934b6cb2b6SLucas Stach 3944b6cb2b6SLucas Stach ret = regmap_update_bits(tve->regmap, TVE_COM_CONF_REG, 3954b6cb2b6SLucas Stach TVE_DAC_SAMP_RATE_MASK, val); 3964b6cb2b6SLucas Stach 3974b6cb2b6SLucas Stach if (ret < 0) { 3984b6cb2b6SLucas Stach dev_err(tve->dev, "failed to set divider: %d\n", ret); 3994b6cb2b6SLucas Stach return ret; 4004b6cb2b6SLucas Stach } 4014b6cb2b6SLucas Stach 4024b6cb2b6SLucas Stach return 0; 4034b6cb2b6SLucas Stach } 4044b6cb2b6SLucas Stach 4054b6cb2b6SLucas Stach static const struct clk_ops clk_tve_di_ops = { 4064b6cb2b6SLucas Stach .round_rate = clk_tve_di_round_rate, 4074b6cb2b6SLucas Stach .set_rate = clk_tve_di_set_rate, 4084b6cb2b6SLucas Stach .recalc_rate = clk_tve_di_recalc_rate, 4094b6cb2b6SLucas Stach }; 4104b6cb2b6SLucas Stach 4114b6cb2b6SLucas Stach static int tve_clk_init(struct imx_tve *tve, void __iomem *base) 4124b6cb2b6SLucas Stach { 4134b6cb2b6SLucas Stach const char *tve_di_parent[1]; 4144b6cb2b6SLucas Stach struct clk_init_data init = { 4154b6cb2b6SLucas Stach .name = "tve_di", 4164b6cb2b6SLucas Stach .ops = &clk_tve_di_ops, 4174b6cb2b6SLucas Stach .num_parents = 1, 4184b6cb2b6SLucas Stach .flags = 0, 4194b6cb2b6SLucas Stach }; 4204b6cb2b6SLucas Stach 4214b6cb2b6SLucas Stach tve_di_parent[0] = __clk_get_name(tve->clk); 4224b6cb2b6SLucas Stach init.parent_names = (const char **)&tve_di_parent; 4234b6cb2b6SLucas Stach 4244b6cb2b6SLucas Stach tve->clk_hw_di.init = &init; 4254b6cb2b6SLucas Stach tve->di_clk = devm_clk_register(tve->dev, &tve->clk_hw_di); 4264b6cb2b6SLucas Stach if (IS_ERR(tve->di_clk)) { 4274b6cb2b6SLucas Stach dev_err(tve->dev, "failed to register TVE output clock: %ld\n", 4284b6cb2b6SLucas Stach PTR_ERR(tve->di_clk)); 4294b6cb2b6SLucas Stach return PTR_ERR(tve->di_clk); 4304b6cb2b6SLucas Stach } 4314b6cb2b6SLucas Stach 4324b6cb2b6SLucas Stach return 0; 4334b6cb2b6SLucas Stach } 4344b6cb2b6SLucas Stach 4354b6cb2b6SLucas Stach static void imx_tve_disable_regulator(void *data) 4364b6cb2b6SLucas Stach { 4374b6cb2b6SLucas Stach struct imx_tve *tve = data; 4384b6cb2b6SLucas Stach 4394b6cb2b6SLucas Stach regulator_disable(tve->dac_reg); 4404b6cb2b6SLucas Stach } 4414b6cb2b6SLucas Stach 4424b6cb2b6SLucas Stach static bool imx_tve_readable_reg(struct device *dev, unsigned int reg) 4434b6cb2b6SLucas Stach { 4444b6cb2b6SLucas Stach return (reg % 4 == 0) && (reg <= 0xdc); 4454b6cb2b6SLucas Stach } 4464b6cb2b6SLucas Stach 4474b6cb2b6SLucas Stach static struct regmap_config tve_regmap_config = { 4484b6cb2b6SLucas Stach .reg_bits = 32, 4494b6cb2b6SLucas Stach .val_bits = 32, 4504b6cb2b6SLucas Stach .reg_stride = 4, 4514b6cb2b6SLucas Stach 4524b6cb2b6SLucas Stach .readable_reg = imx_tve_readable_reg, 4534b6cb2b6SLucas Stach 4544b6cb2b6SLucas Stach .fast_io = true, 4554b6cb2b6SLucas Stach 4564b6cb2b6SLucas Stach .max_register = 0xdc, 4574b6cb2b6SLucas Stach }; 4584b6cb2b6SLucas Stach 4594b6cb2b6SLucas Stach static const char * const imx_tve_modes[] = { 4604b6cb2b6SLucas Stach [TVE_MODE_TVOUT] = "tvout", 4614b6cb2b6SLucas Stach [TVE_MODE_VGA] = "vga", 4624b6cb2b6SLucas Stach }; 4634b6cb2b6SLucas Stach 4644b6cb2b6SLucas Stach static int of_get_tve_mode(struct device_node *np) 4654b6cb2b6SLucas Stach { 4664b6cb2b6SLucas Stach const char *bm; 4674b6cb2b6SLucas Stach int ret, i; 4684b6cb2b6SLucas Stach 4694b6cb2b6SLucas Stach ret = of_property_read_string(np, "fsl,tve-mode", &bm); 4704b6cb2b6SLucas Stach if (ret < 0) 4714b6cb2b6SLucas Stach return ret; 4724b6cb2b6SLucas Stach 4734b6cb2b6SLucas Stach for (i = 0; i < ARRAY_SIZE(imx_tve_modes); i++) 4744b6cb2b6SLucas Stach if (!strcasecmp(bm, imx_tve_modes[i])) 4754b6cb2b6SLucas Stach return i; 4764b6cb2b6SLucas Stach 4774b6cb2b6SLucas Stach return -EINVAL; 4784b6cb2b6SLucas Stach } 4794b6cb2b6SLucas Stach 4804b6cb2b6SLucas Stach static int imx_tve_bind(struct device *dev, struct device *master, void *data) 4814b6cb2b6SLucas Stach { 4824b6cb2b6SLucas Stach struct drm_device *drm = data; 4834b6cb2b6SLucas Stach struct imx_tve *tve = dev_get_drvdata(dev); 4844b6cb2b6SLucas Stach struct imx_tve_encoder *tvee; 4854b6cb2b6SLucas Stach struct drm_encoder *encoder; 4864b6cb2b6SLucas Stach struct drm_connector *connector; 4874b6cb2b6SLucas Stach int encoder_type; 4884b6cb2b6SLucas Stach int ret; 4894b6cb2b6SLucas Stach 4904b6cb2b6SLucas Stach encoder_type = tve->mode == TVE_MODE_VGA ? 4914b6cb2b6SLucas Stach DRM_MODE_ENCODER_DAC : DRM_MODE_ENCODER_TVDAC; 4924b6cb2b6SLucas Stach 4934b6cb2b6SLucas Stach tvee = drmm_simple_encoder_alloc(drm, struct imx_tve_encoder, encoder, 4944b6cb2b6SLucas Stach encoder_type); 4954b6cb2b6SLucas Stach if (IS_ERR(tvee)) 4964b6cb2b6SLucas Stach return PTR_ERR(tvee); 4974b6cb2b6SLucas Stach 4984b6cb2b6SLucas Stach tvee->tve = tve; 4994b6cb2b6SLucas Stach encoder = &tvee->encoder; 5004b6cb2b6SLucas Stach connector = &tvee->connector; 5014b6cb2b6SLucas Stach 5024b6cb2b6SLucas Stach ret = imx_drm_encoder_parse_of(drm, encoder, tve->dev->of_node); 5034b6cb2b6SLucas Stach if (ret) 5044b6cb2b6SLucas Stach return ret; 5054b6cb2b6SLucas Stach 5064b6cb2b6SLucas Stach drm_encoder_helper_add(encoder, &imx_tve_encoder_helper_funcs); 5074b6cb2b6SLucas Stach 5084b6cb2b6SLucas Stach drm_connector_helper_add(connector, &imx_tve_connector_helper_funcs); 5094b6cb2b6SLucas Stach ret = drm_connector_init_with_ddc(drm, connector, 5104b6cb2b6SLucas Stach &imx_tve_connector_funcs, 5114b6cb2b6SLucas Stach DRM_MODE_CONNECTOR_VGA, tve->ddc); 5124b6cb2b6SLucas Stach if (ret) 5134b6cb2b6SLucas Stach return ret; 5144b6cb2b6SLucas Stach 5154b6cb2b6SLucas Stach return drm_connector_attach_encoder(connector, encoder); 5164b6cb2b6SLucas Stach } 5174b6cb2b6SLucas Stach 5184b6cb2b6SLucas Stach static const struct component_ops imx_tve_ops = { 5194b6cb2b6SLucas Stach .bind = imx_tve_bind, 5204b6cb2b6SLucas Stach }; 5214b6cb2b6SLucas Stach 5224b6cb2b6SLucas Stach static int imx_tve_probe(struct platform_device *pdev) 5234b6cb2b6SLucas Stach { 5244b6cb2b6SLucas Stach struct device *dev = &pdev->dev; 5254b6cb2b6SLucas Stach struct device_node *np = dev->of_node; 5264b6cb2b6SLucas Stach struct device_node *ddc_node; 5274b6cb2b6SLucas Stach struct imx_tve *tve; 5284b6cb2b6SLucas Stach void __iomem *base; 5294b6cb2b6SLucas Stach unsigned int val; 5304b6cb2b6SLucas Stach int irq; 5314b6cb2b6SLucas Stach int ret; 5324b6cb2b6SLucas Stach 5334b6cb2b6SLucas Stach tve = devm_kzalloc(dev, sizeof(*tve), GFP_KERNEL); 5344b6cb2b6SLucas Stach if (!tve) 5354b6cb2b6SLucas Stach return -ENOMEM; 5364b6cb2b6SLucas Stach 5374b6cb2b6SLucas Stach tve->dev = dev; 5384b6cb2b6SLucas Stach 5394b6cb2b6SLucas Stach ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0); 5404b6cb2b6SLucas Stach if (ddc_node) { 5414b6cb2b6SLucas Stach tve->ddc = of_find_i2c_adapter_by_node(ddc_node); 5424b6cb2b6SLucas Stach of_node_put(ddc_node); 5434b6cb2b6SLucas Stach } 5444b6cb2b6SLucas Stach 5454b6cb2b6SLucas Stach tve->mode = of_get_tve_mode(np); 5464b6cb2b6SLucas Stach if (tve->mode != TVE_MODE_VGA) { 5474b6cb2b6SLucas Stach dev_err(dev, "only VGA mode supported, currently\n"); 5484b6cb2b6SLucas Stach return -EINVAL; 5494b6cb2b6SLucas Stach } 5504b6cb2b6SLucas Stach 5514b6cb2b6SLucas Stach if (tve->mode == TVE_MODE_VGA) { 5524b6cb2b6SLucas Stach ret = of_property_read_u32(np, "fsl,hsync-pin", 5534b6cb2b6SLucas Stach &tve->di_hsync_pin); 5544b6cb2b6SLucas Stach 5554b6cb2b6SLucas Stach if (ret < 0) { 5564b6cb2b6SLucas Stach dev_err(dev, "failed to get hsync pin\n"); 5574b6cb2b6SLucas Stach return ret; 5584b6cb2b6SLucas Stach } 5594b6cb2b6SLucas Stach 5604b6cb2b6SLucas Stach ret = of_property_read_u32(np, "fsl,vsync-pin", 5614b6cb2b6SLucas Stach &tve->di_vsync_pin); 5624b6cb2b6SLucas Stach 5634b6cb2b6SLucas Stach if (ret < 0) { 5644b6cb2b6SLucas Stach dev_err(dev, "failed to get vsync pin\n"); 5654b6cb2b6SLucas Stach return ret; 5664b6cb2b6SLucas Stach } 5674b6cb2b6SLucas Stach } 5684b6cb2b6SLucas Stach 5694b6cb2b6SLucas Stach base = devm_platform_ioremap_resource(pdev, 0); 5704b6cb2b6SLucas Stach if (IS_ERR(base)) 5714b6cb2b6SLucas Stach return PTR_ERR(base); 5724b6cb2b6SLucas Stach 5734b6cb2b6SLucas Stach tve_regmap_config.lock_arg = tve; 5744b6cb2b6SLucas Stach tve->regmap = devm_regmap_init_mmio_clk(dev, "tve", base, 5754b6cb2b6SLucas Stach &tve_regmap_config); 5764b6cb2b6SLucas Stach if (IS_ERR(tve->regmap)) { 5774b6cb2b6SLucas Stach dev_err(dev, "failed to init regmap: %ld\n", 5784b6cb2b6SLucas Stach PTR_ERR(tve->regmap)); 5794b6cb2b6SLucas Stach return PTR_ERR(tve->regmap); 5804b6cb2b6SLucas Stach } 5814b6cb2b6SLucas Stach 5824b6cb2b6SLucas Stach irq = platform_get_irq(pdev, 0); 5834b6cb2b6SLucas Stach if (irq < 0) 5844b6cb2b6SLucas Stach return irq; 5854b6cb2b6SLucas Stach 5864b6cb2b6SLucas Stach ret = devm_request_threaded_irq(dev, irq, NULL, 5874b6cb2b6SLucas Stach imx_tve_irq_handler, IRQF_ONESHOT, 5884b6cb2b6SLucas Stach "imx-tve", tve); 5894b6cb2b6SLucas Stach if (ret < 0) { 5904b6cb2b6SLucas Stach dev_err(dev, "failed to request irq: %d\n", ret); 5914b6cb2b6SLucas Stach return ret; 5924b6cb2b6SLucas Stach } 5934b6cb2b6SLucas Stach 5944b6cb2b6SLucas Stach tve->dac_reg = devm_regulator_get(dev, "dac"); 5954b6cb2b6SLucas Stach if (!IS_ERR(tve->dac_reg)) { 5964b6cb2b6SLucas Stach if (regulator_get_voltage(tve->dac_reg) != IMX_TVE_DAC_VOLTAGE) 5974b6cb2b6SLucas Stach dev_warn(dev, "dac voltage is not %d uV\n", IMX_TVE_DAC_VOLTAGE); 5984b6cb2b6SLucas Stach ret = regulator_enable(tve->dac_reg); 5994b6cb2b6SLucas Stach if (ret) 6004b6cb2b6SLucas Stach return ret; 6014b6cb2b6SLucas Stach ret = devm_add_action_or_reset(dev, imx_tve_disable_regulator, tve); 6024b6cb2b6SLucas Stach if (ret) 6034b6cb2b6SLucas Stach return ret; 6044b6cb2b6SLucas Stach } 6054b6cb2b6SLucas Stach 6064b6cb2b6SLucas Stach tve->clk = devm_clk_get(dev, "tve"); 6074b6cb2b6SLucas Stach if (IS_ERR(tve->clk)) { 6084b6cb2b6SLucas Stach dev_err(dev, "failed to get high speed tve clock: %ld\n", 6094b6cb2b6SLucas Stach PTR_ERR(tve->clk)); 6104b6cb2b6SLucas Stach return PTR_ERR(tve->clk); 6114b6cb2b6SLucas Stach } 6124b6cb2b6SLucas Stach 6134b6cb2b6SLucas Stach /* this is the IPU DI clock input selector, can be parented to tve_di */ 6144b6cb2b6SLucas Stach tve->di_sel_clk = devm_clk_get(dev, "di_sel"); 6154b6cb2b6SLucas Stach if (IS_ERR(tve->di_sel_clk)) { 6164b6cb2b6SLucas Stach dev_err(dev, "failed to get ipu di mux clock: %ld\n", 6174b6cb2b6SLucas Stach PTR_ERR(tve->di_sel_clk)); 6184b6cb2b6SLucas Stach return PTR_ERR(tve->di_sel_clk); 6194b6cb2b6SLucas Stach } 6204b6cb2b6SLucas Stach 6214b6cb2b6SLucas Stach ret = tve_clk_init(tve, base); 6224b6cb2b6SLucas Stach if (ret < 0) 6234b6cb2b6SLucas Stach return ret; 6244b6cb2b6SLucas Stach 6254b6cb2b6SLucas Stach ret = regmap_read(tve->regmap, TVE_COM_CONF_REG, &val); 6264b6cb2b6SLucas Stach if (ret < 0) { 6274b6cb2b6SLucas Stach dev_err(dev, "failed to read configuration register: %d\n", 6284b6cb2b6SLucas Stach ret); 6294b6cb2b6SLucas Stach return ret; 6304b6cb2b6SLucas Stach } 6314b6cb2b6SLucas Stach if (val != 0x00100000) { 6324b6cb2b6SLucas Stach dev_err(dev, "configuration register default value indicates this is not a TVEv2\n"); 6334b6cb2b6SLucas Stach return -ENODEV; 6344b6cb2b6SLucas Stach } 6354b6cb2b6SLucas Stach 6364b6cb2b6SLucas Stach /* disable cable detection for VGA mode */ 6374b6cb2b6SLucas Stach ret = regmap_write(tve->regmap, TVE_CD_CONT_REG, 0); 6384b6cb2b6SLucas Stach if (ret) 6394b6cb2b6SLucas Stach return ret; 6404b6cb2b6SLucas Stach 6414b6cb2b6SLucas Stach platform_set_drvdata(pdev, tve); 6424b6cb2b6SLucas Stach 6434b6cb2b6SLucas Stach return component_add(dev, &imx_tve_ops); 6444b6cb2b6SLucas Stach } 6454b6cb2b6SLucas Stach 6463095f112SUwe Kleine-König static void imx_tve_remove(struct platform_device *pdev) 6474b6cb2b6SLucas Stach { 6484b6cb2b6SLucas Stach component_del(&pdev->dev, &imx_tve_ops); 6494b6cb2b6SLucas Stach } 6504b6cb2b6SLucas Stach 6514b6cb2b6SLucas Stach static const struct of_device_id imx_tve_dt_ids[] = { 6524b6cb2b6SLucas Stach { .compatible = "fsl,imx53-tve", }, 6534b6cb2b6SLucas Stach { /* sentinel */ } 6544b6cb2b6SLucas Stach }; 6554b6cb2b6SLucas Stach MODULE_DEVICE_TABLE(of, imx_tve_dt_ids); 6564b6cb2b6SLucas Stach 6574b6cb2b6SLucas Stach static struct platform_driver imx_tve_driver = { 6584b6cb2b6SLucas Stach .probe = imx_tve_probe, 6593095f112SUwe Kleine-König .remove_new = imx_tve_remove, 6604b6cb2b6SLucas Stach .driver = { 6614b6cb2b6SLucas Stach .of_match_table = imx_tve_dt_ids, 6624b6cb2b6SLucas Stach .name = "imx-tve", 6634b6cb2b6SLucas Stach }, 6644b6cb2b6SLucas Stach }; 6654b6cb2b6SLucas Stach 6664b6cb2b6SLucas Stach module_platform_driver(imx_tve_driver); 6674b6cb2b6SLucas Stach 6684b6cb2b6SLucas Stach MODULE_DESCRIPTION("i.MX Television Encoder driver"); 6694b6cb2b6SLucas Stach MODULE_AUTHOR("Philipp Zabel, Pengutronix"); 6704b6cb2b6SLucas Stach MODULE_LICENSE("GPL"); 6714b6cb2b6SLucas Stach MODULE_ALIAS("platform:imx-tve"); 672