Advertisement
Guest User

Untitled

a guest
Feb 23rd, 2018
334
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 20.25 KB | None | 0 0
  1. /*
  2.  * Copyright (C) 2015 Free Electrons
  3.  * Copyright (C) 2015 NextThing Co
  4.  *
  5.  * Maxime Ripard <maxime.ripard@free-electrons.com>
  6.  *
  7.  * This program is free software; you can redistribute it and/or
  8.  * modify it under the terms of the GNU General Public License as
  9.  * published by the Free Software Foundation; either version 2 of
  10.  * the License, or (at your option) any later version.
  11.  */
  12.  
  13. #include <linux/clk.h>
  14. #include <linux/component.h>
  15. #include <linux/of_address.h>
  16. #include <linux/of_device.h>
  17. #include <linux/regmap.h>
  18. #include <linux/reset.h>
  19.  
  20. #include <drm/drmP.h>
  21. #include <drm/drm_atomic_helper.h>
  22. #include <drm/drm_crtc_helper.h>
  23. #include <drm/drm_of.h>
  24. #include <drm/drm_panel.h>
  25.  
  26. #include "sun4i_crtc.h"
  27. #include "sun4i_drv.h"
  28. #include "sun4i_tcon.h"
  29. #include "sunxi_engine.h"
  30.  
  31. #define SUN4I_TVE_EN_REG        0x000
  32. #define SUN4I_TVE_EN_DAC_MAP_MASK       GENMASK(19, 4)
  33. #define SUN4I_TVE_EN_DAC_MAP(dac, out)      (((out) & 0xf) << (dac + 1) * 4)
  34. #define SUN4I_TVE_EN_ENABLE         BIT(0)
  35.  
  36. #define SUN4I_TVE_CFG0_REG      0x004
  37. #define SUN4I_TVE_CFG0_DAC_CONTROL_54M      BIT(26)
  38. #define SUN4I_TVE_CFG0_CORE_DATAPATH_54M    BIT(25)
  39. #define SUN4I_TVE_CFG0_CORE_CONTROL_54M     BIT(24)
  40. #define SUN4I_TVE_CFG0_YC_EN            BIT(17)
  41. #define SUN4I_TVE_CFG0_COMP_EN          BIT(16)
  42. #define SUN4I_TVE_CFG0_RES(x)           ((x) & 0xf)
  43. #define SUN4I_TVE_CFG0_RES_480i         SUN4I_TVE_CFG0_RES(0)
  44. #define SUN4I_TVE_CFG0_RES_576i         SUN4I_TVE_CFG0_RES(1)
  45.  
  46. #define SUN4I_TVE_DAC0_REG      0x008
  47. #define SUN4I_TVE_DAC0_CLOCK_INVERT     BIT(24)
  48. #define SUN4I_TVE_DAC0_LUMA(x)          (((x) & 3) << 20)
  49. #define SUN4I_TVE_DAC0_LUMA_0_4         SUN4I_TVE_DAC0_LUMA(3)
  50. #define SUN4I_TVE_DAC0_CHROMA(x)        (((x) & 3) << 18)
  51. #define SUN4I_TVE_DAC0_CHROMA_0_75      SUN4I_TVE_DAC0_CHROMA(3)
  52. #define SUN4I_TVE_DAC0_INTERNAL_DAC(x)      (((x) & 3) << 16)
  53. #define SUN4I_TVE_DAC0_INTERNAL_DAC_37_5_OHMS   SUN4I_TVE_DAC0_INTERNAL_DAC(3)
  54. #define SUN4I_TVE_DAC0_DAC_EN(dac)      BIT(dac)
  55.  
  56. #define SUN4I_TVE_NOTCH_REG     0x00c
  57. #define SUN4I_TVE_NOTCH_DAC0_TO_DAC_DLY(dac, x) ((4 - (x)) << (dac * 3))
  58.  
  59. #define SUN4I_TVE_CHROMA_FREQ_REG   0x010
  60.  
  61. #define SUN4I_TVE_PORCH_REG     0x014
  62. #define SUN4I_TVE_PORCH_BACK(x)         ((x) << 16)
  63. #define SUN4I_TVE_PORCH_FRONT(x)        (x)
  64.  
  65. #define SUN4I_TVE_LINE_REG      0x01c
  66. #define SUN4I_TVE_LINE_FIRST(x)         ((x) << 16)
  67. #define SUN4I_TVE_LINE_NUMBER(x)        (x)
  68.  
  69. #define SUN4I_TVE_LEVEL_REG     0x020
  70. #define SUN4I_TVE_LEVEL_BLANK(x)        ((x) << 16)
  71. #define SUN4I_TVE_LEVEL_BLACK(x)        (x)
  72.  
  73. #define SUN4I_TVE_DAC1_REG      0x024
  74. #define SUN4I_TVE_DAC1_AMPLITUDE(dac, x)    ((x) << (dac * 8))
  75.  
  76. #define SUN4I_TVE_DETECT_STA_REG    0x038
  77. #define SUN4I_TVE_DETECT_STA_DAC(dac)       BIT((dac * 8))
  78. #define SUN4I_TVE_DETECT_STA_UNCONNECTED        0
  79. #define SUN4I_TVE_DETECT_STA_CONNECTED          1
  80. #define SUN4I_TVE_DETECT_STA_GROUND         2
  81.  
  82. #define SUN4I_TVE_CB_CR_LVL_REG     0x10c
  83. #define SUN4I_TVE_CB_CR_LVL_CR_BURST(x)     ((x) << 8)
  84. #define SUN4I_TVE_CB_CR_LVL_CB_BURST(x)     (x)
  85.  
  86. #define SUN4I_TVE_TINT_BURST_PHASE_REG  0x110
  87. #define SUN4I_TVE_TINT_BURST_PHASE_CHROMA(x)    (x)
  88.  
  89. #define SUN4I_TVE_BURST_WIDTH_REG   0x114
  90. #define SUN4I_TVE_BURST_WIDTH_BREEZEWAY(x)  ((x) << 16)
  91. #define SUN4I_TVE_BURST_WIDTH_BURST_WIDTH(x)    ((x) << 8)
  92. #define SUN4I_TVE_BURST_WIDTH_HSYNC_WIDTH(x)    (x)
  93.  
  94. #define SUN4I_TVE_CB_CR_GAIN_REG    0x118
  95. #define SUN4I_TVE_CB_CR_GAIN_CR(x)      ((x) << 8)
  96. #define SUN4I_TVE_CB_CR_GAIN_CB(x)      (x)
  97.  
  98. #define SUN4I_TVE_SYNC_VBI_REG      0x11c
  99. #define SUN4I_TVE_SYNC_VBI_SYNC(x)      ((x) << 16)
  100. #define SUN4I_TVE_SYNC_VBI_VBLANK(x)        (x)
  101.  
  102. #define SUN4I_TVE_ACTIVE_LINE_REG   0x124
  103. #define SUN4I_TVE_ACTIVE_LINE(x)        (x)
  104.  
  105. #define SUN4I_TVE_CHROMA_REG        0x128
  106. #define SUN4I_TVE_CHROMA_COMP_GAIN(x)       ((x) & 3)
  107. #define SUN4I_TVE_CHROMA_COMP_GAIN_50       SUN4I_TVE_CHROMA_COMP_GAIN(2)
  108.  
  109. #define SUN4I_TVE_12C_REG       0x12c
  110. #define SUN4I_TVE_12C_NOTCH_WIDTH_WIDE      BIT(8)
  111. #define SUN4I_TVE_12C_COMP_YUV_EN       BIT(0)
  112.  
  113. #define SUN4I_TVE_RESYNC_REG        0x130
  114. #define SUN4I_TVE_RESYNC_FIELD          BIT(31)
  115. #define SUN4I_TVE_RESYNC_LINE(x)        ((x) << 16)
  116. #define SUN4I_TVE_RESYNC_PIXEL(x)       (x)
  117.  
  118. #define SUN4I_TVE_SLAVE_REG     0x134
  119.  
  120. #define SUN4I_TVE_WSS_DATA2_REG     0x244
  121.  
  122. struct color_gains {
  123.     u16 cb;
  124.     u16 cr;
  125. };
  126.  
  127. struct burst_levels {
  128.     u16 cb;
  129.     u16 cr;
  130. };
  131.  
  132. struct video_levels {
  133.     u16 black;
  134.     u16 blank;
  135. };
  136.  
  137. struct resync_parameters {
  138.     bool    field;
  139.     u16 line;
  140.     u16 pixel;
  141. };
  142.  
  143. struct tv_mode {
  144.     char        *name;
  145.  
  146.     u32     mode;
  147.     u32     chroma_freq;
  148.     u16     back_porch;
  149.     u16     front_porch;
  150.     u16     line_number;
  151.     u16     vblank_level;
  152.  
  153.     u32     hdisplay;
  154.     u16     hfront_porch;
  155.     u16     hsync_len;
  156.     u16     hback_porch;
  157.  
  158.     u32     vdisplay;
  159.     u16     vfront_porch;
  160.     u16     vsync_len;
  161.     u16     vback_porch;
  162.  
  163.     bool        yc_en;
  164.     bool        dac3_en;
  165.     bool        dac_bit25_en;
  166.  
  167.     const struct color_gains    *color_gains;
  168.     const struct burst_levels   *burst_levels;
  169.     const struct video_levels   *video_levels;
  170.     const struct resync_parameters  *resync_params;
  171. };
  172.  
  173. struct sun4i_tv_quirks {
  174.     int fixed_divider;
  175. };
  176.  
  177. struct sun4i_tv {
  178.     struct drm_connector    connector;
  179.     struct drm_encoder  encoder;
  180.  
  181.     struct clk      *clk;
  182.     struct clk      *mod_clk;
  183.     struct regmap       *regs;
  184.     struct reset_control    *reset;
  185.  
  186.     const struct sun4i_tv_quirks *quirks;
  187.  
  188.     struct sun4i_drv    *drv;
  189. };
  190.  
  191. static const struct video_levels ntsc_video_levels = {
  192.     .black = 282,   .blank = 240,
  193. };
  194.  
  195. static const struct video_levels pal_video_levels = {
  196.     .black = 252,   .blank = 252,
  197. };
  198.  
  199. static const struct burst_levels ntsc_burst_levels = {
  200.     .cb = 79,   .cr = 0,
  201. };
  202.  
  203. static const struct burst_levels pal_burst_levels = {
  204.     .cb = 40,   .cr = 40,
  205. };
  206.  
  207. static const struct color_gains ntsc_color_gains = {
  208.     .cb = 160,  .cr = 160,
  209. };
  210.  
  211. static const struct color_gains pal_color_gains = {
  212.     .cb = 224,  .cr = 224,
  213. };
  214.  
  215. static const struct resync_parameters ntsc_resync_parameters = {
  216.     .field = false, .line = 14, .pixel = 12,
  217. };
  218.  
  219. static const struct resync_parameters pal_resync_parameters = {
  220.     .field = true,  .line = 13, .pixel = 12,
  221. };
  222.  
  223. static const struct tv_mode tv_modes[] = {
  224.     {
  225.         .name       = "NTSC",
  226.         .mode       = SUN4I_TVE_CFG0_RES_480i,
  227.         .chroma_freq    = 0x21f07c1f,
  228.         .yc_en      = true,
  229.         .dac3_en    = true,
  230.         .dac_bit25_en   = true,
  231.  
  232.         .back_porch = 118,
  233.         .front_porch    = 32,
  234.         .line_number    = 525,
  235.  
  236.         .hdisplay   = 720,
  237.         .hfront_porch   = 18,
  238.         .hsync_len  = 2,
  239.         .hback_porch    = 118,
  240.  
  241.         .vdisplay   = 480,
  242.         .vfront_porch   = 26,
  243.         .vsync_len  = 2,
  244.         .vback_porch    = 17,
  245.  
  246.         .vblank_level   = 240,
  247.  
  248.         .color_gains    = &ntsc_color_gains,
  249.         .burst_levels   = &ntsc_burst_levels,
  250.         .video_levels   = &ntsc_video_levels,
  251.         .resync_params  = &ntsc_resync_parameters,
  252.     },
  253.     {
  254.         .name       = "PAL",
  255.         .mode       = SUN4I_TVE_CFG0_RES_576i,
  256.         .chroma_freq    = 0x2a098acb,
  257.  
  258.         .back_porch = 138,
  259.         .front_porch    = 24,
  260.         .line_number    = 625,
  261.  
  262.         .hdisplay   = 720,
  263.         .hfront_porch   = 3,
  264.         .hsync_len  = 2,
  265.         .hback_porch    = 139,
  266.  
  267.         .vdisplay   = 576,
  268.         .vfront_porch   = 28,
  269.         .vsync_len  = 2,
  270.         .vback_porch    = 19,
  271.  
  272.         .vblank_level   = 252,
  273.  
  274.         .color_gains    = &pal_color_gains,
  275.         .burst_levels   = &pal_burst_levels,
  276.         .video_levels   = &pal_video_levels,
  277.         .resync_params  = &pal_resync_parameters,
  278.     },
  279. };
  280.  
  281. static inline struct sun4i_tv *
  282. drm_encoder_to_sun4i_tv(struct drm_encoder *encoder)
  283. {
  284.     DRM_DEBUG_DRIVER("TVE: drm_encoder_to_sun4i_tv\n");
  285.    
  286.     return container_of(encoder, struct sun4i_tv,
  287.                 encoder);
  288. }
  289.  
  290. static inline struct sun4i_tv *
  291. drm_connector_to_sun4i_tv(struct drm_connector *connector)
  292. {
  293.     DRM_DEBUG_DRIVER("TVE: drm_connector_to_sun4i_tv\n");
  294.    
  295.     return container_of(connector, struct sun4i_tv,
  296.                 connector);
  297. }
  298.  
  299. /*
  300.  * FIXME: If only the drm_display_mode private field was usable, this
  301.  * could go away...
  302.  *
  303.  * So far, it doesn't seem to be preserved when the mode is passed by
  304.  * to mode_set for some reason.
  305.  */
  306. static const struct tv_mode *sun4i_tv_find_tv_by_mode(const struct drm_display_mode *mode)
  307. {
  308.     int i;
  309.     DRM_DEBUG_DRIVER("TVE: sun4i_tv_find_tv_by_mode\n");
  310.  
  311.     /* First try to identify the mode by name */
  312.     for (i = 0; i < ARRAY_SIZE(tv_modes); i++) {
  313.         const struct tv_mode *tv_mode = &tv_modes[i];
  314.  
  315.         DRM_DEBUG_DRIVER("Comparing mode %s vs %s",
  316.                  mode->name, tv_mode->name);
  317.  
  318.         if (!strcmp(mode->name, tv_mode->name))
  319.             return tv_mode;
  320.     }
  321.  
  322.     /* Then by number of lines */
  323.     for (i = 0; i < ARRAY_SIZE(tv_modes); i++) {
  324.         const struct tv_mode *tv_mode = &tv_modes[i];
  325.  
  326.         DRM_DEBUG_DRIVER("Comparing mode %s vs %s (X: %d vs %d)",
  327.                  mode->name, tv_mode->name,
  328.                  mode->vdisplay, tv_mode->vdisplay);
  329.  
  330.         if (mode->vdisplay == tv_mode->vdisplay)
  331.             return tv_mode;
  332.     }
  333.  
  334.     return NULL;
  335. }
  336.  
  337. static void sun4i_tv_mode_to_drm_mode(const struct tv_mode *tv_mode,
  338.                       struct drm_display_mode *mode)
  339. {
  340.     DRM_DEBUG_DRIVER("Creating mode %s\n", mode->name);
  341.  
  342.     mode->type = DRM_MODE_TYPE_DRIVER;
  343.     mode->clock = 13500;
  344.     mode->flags = DRM_MODE_FLAG_INTERLACE;
  345.  
  346.     mode->hdisplay = tv_mode->hdisplay;
  347.     mode->hsync_start = mode->hdisplay + tv_mode->hfront_porch;
  348.     mode->hsync_end = mode->hsync_start + tv_mode->hsync_len;
  349.     mode->htotal = mode->hsync_end  + tv_mode->hback_porch;
  350.  
  351.     mode->vdisplay = tv_mode->vdisplay;
  352.     mode->vsync_start = mode->vdisplay + tv_mode->vfront_porch;
  353.     mode->vsync_end = mode->vsync_start + tv_mode->vsync_len;
  354.     mode->vtotal = mode->vsync_end  + tv_mode->vback_porch;
  355. }
  356.  
  357. static void sun4i_tv_disable(struct drm_encoder *encoder)
  358. {
  359.     struct sun4i_tv *tv = drm_encoder_to_sun4i_tv(encoder);
  360.     struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc);
  361.     struct sun4i_tcon *tcon = crtc->tcon;
  362.  
  363.     DRM_DEBUG_DRIVER("Disabling the TV Output\n");
  364.  
  365.     sun4i_tcon_channel_disable(tcon, 1);
  366.  
  367.     regmap_update_bits(tv->regs, SUN4I_TVE_EN_REG,
  368.                SUN4I_TVE_EN_ENABLE,
  369.                0);
  370.  
  371.     sunxi_engine_disable_color_correction(crtc->engine);
  372. }
  373.  
  374. static void sun4i_tv_enable(struct drm_encoder *encoder)
  375. {
  376.     struct sun4i_tv *tv = drm_encoder_to_sun4i_tv(encoder);
  377.     struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc);
  378.     struct sun4i_tcon *tcon = crtc->tcon;
  379.  
  380.     DRM_DEBUG_DRIVER("Enabling the TV Output\n");
  381.  
  382.     sunxi_engine_apply_color_correction(crtc->engine);
  383.  
  384.     regmap_update_bits(tv->regs, SUN4I_TVE_EN_REG,
  385.                SUN4I_TVE_EN_ENABLE,
  386.                SUN4I_TVE_EN_ENABLE);
  387.  
  388.     sun4i_tcon_channel_enable(tcon, 1);
  389. }
  390.  
  391. static void sun4i_tv_mode_set(struct drm_encoder *encoder,
  392.                   struct drm_display_mode *mode,
  393.                   struct drm_display_mode *adjusted_mode)
  394. {
  395.     struct sun4i_tv *tv = drm_encoder_to_sun4i_tv(encoder);
  396.     struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc);
  397.     struct sun4i_tcon *tcon = crtc->tcon;
  398.     const struct tv_mode *tv_mode = sun4i_tv_find_tv_by_mode(mode);
  399.  
  400.     DRM_DEBUG_DRIVER("TVE: sun4i_tv_mode_set\n");
  401.  
  402.     if (tv->quirks->fixed_divider) {
  403.         DRM_DEBUG_DRIVER("Applying fixed divider %d on TVE clock\n",
  404.                  tv->quirks->fixed_divider);
  405.         mode->crtc_clock *= tv->quirks->fixed_divider;
  406.     }
  407.  
  408.     sun4i_tcon1_mode_set(tcon, mode);
  409.     sun4i_tcon_set_mux(tcon, 1, encoder);
  410.  
  411.     /* Enable and map the DAC to the output */
  412.     regmap_update_bits(tv->regs, SUN4I_TVE_EN_REG,
  413.                SUN4I_TVE_EN_DAC_MAP_MASK,
  414.                SUN4I_TVE_EN_DAC_MAP(0, 1) |
  415.                SUN4I_TVE_EN_DAC_MAP(1, 2) |
  416.                SUN4I_TVE_EN_DAC_MAP(2, 3) |
  417.                SUN4I_TVE_EN_DAC_MAP(3, 4));
  418.  
  419.     /* Set PAL settings */
  420.     regmap_write(tv->regs, SUN4I_TVE_CFG0_REG,
  421.              tv_mode->mode |
  422.              (tv_mode->yc_en ? SUN4I_TVE_CFG0_YC_EN : 0) |
  423.              SUN4I_TVE_CFG0_COMP_EN |
  424.              SUN4I_TVE_CFG0_DAC_CONTROL_54M |
  425.              SUN4I_TVE_CFG0_CORE_DATAPATH_54M |
  426.              SUN4I_TVE_CFG0_CORE_CONTROL_54M);
  427.  
  428.     /* Configure the DAC for a composite output */
  429.     regmap_write(tv->regs, SUN4I_TVE_DAC0_REG,
  430.              SUN4I_TVE_DAC0_DAC_EN(0) |
  431.              (tv_mode->dac3_en ? SUN4I_TVE_DAC0_DAC_EN(3) : 0) |
  432.              SUN4I_TVE_DAC0_INTERNAL_DAC_37_5_OHMS |
  433.              SUN4I_TVE_DAC0_CHROMA_0_75 |
  434.              SUN4I_TVE_DAC0_LUMA_0_4 |
  435.              SUN4I_TVE_DAC0_CLOCK_INVERT |
  436.              (tv_mode->dac_bit25_en ? BIT(25) : 0) |
  437.              BIT(30));
  438.  
  439.     /* Configure the sample delay between DAC0 and the other DAC */
  440.     regmap_write(tv->regs, SUN4I_TVE_NOTCH_REG,
  441.              SUN4I_TVE_NOTCH_DAC0_TO_DAC_DLY(1, 0) |
  442.              SUN4I_TVE_NOTCH_DAC0_TO_DAC_DLY(2, 0));
  443.  
  444.     regmap_write(tv->regs, SUN4I_TVE_CHROMA_FREQ_REG,
  445.              tv_mode->chroma_freq);
  446.  
  447.     /* Set the front and back porch */
  448.     regmap_write(tv->regs, SUN4I_TVE_PORCH_REG,
  449.              SUN4I_TVE_PORCH_BACK(tv_mode->back_porch) |
  450.              SUN4I_TVE_PORCH_FRONT(tv_mode->front_porch));
  451.  
  452.     /* Set the lines setup */
  453.     regmap_write(tv->regs, SUN4I_TVE_LINE_REG,
  454.              SUN4I_TVE_LINE_FIRST(22) |
  455.              SUN4I_TVE_LINE_NUMBER(tv_mode->line_number));
  456.  
  457.     regmap_write(tv->regs, SUN4I_TVE_LEVEL_REG,
  458.              SUN4I_TVE_LEVEL_BLANK(tv_mode->video_levels->blank) |
  459.              SUN4I_TVE_LEVEL_BLACK(tv_mode->video_levels->black));
  460.  
  461.     regmap_write(tv->regs, SUN4I_TVE_DAC1_REG,
  462.              SUN4I_TVE_DAC1_AMPLITUDE(0, 0x18) |
  463.              SUN4I_TVE_DAC1_AMPLITUDE(1, 0x18) |
  464.              SUN4I_TVE_DAC1_AMPLITUDE(2, 0x18) |
  465.              SUN4I_TVE_DAC1_AMPLITUDE(3, 0x18));
  466.  
  467.     regmap_write(tv->regs, SUN4I_TVE_CB_CR_LVL_REG,
  468.              SUN4I_TVE_CB_CR_LVL_CB_BURST(tv_mode->burst_levels->cb) |
  469.              SUN4I_TVE_CB_CR_LVL_CR_BURST(tv_mode->burst_levels->cr));
  470.  
  471.     /* Set burst width for a composite output */
  472.     regmap_write(tv->regs, SUN4I_TVE_BURST_WIDTH_REG,
  473.              SUN4I_TVE_BURST_WIDTH_HSYNC_WIDTH(126) |
  474.              SUN4I_TVE_BURST_WIDTH_BURST_WIDTH(68) |
  475.              SUN4I_TVE_BURST_WIDTH_BREEZEWAY(22));
  476.  
  477.     regmap_write(tv->regs, SUN4I_TVE_CB_CR_GAIN_REG,
  478.              SUN4I_TVE_CB_CR_GAIN_CB(tv_mode->color_gains->cb) |
  479.              SUN4I_TVE_CB_CR_GAIN_CR(tv_mode->color_gains->cr));
  480.  
  481.     regmap_write(tv->regs, SUN4I_TVE_SYNC_VBI_REG,
  482.              SUN4I_TVE_SYNC_VBI_SYNC(0x10) |
  483.              SUN4I_TVE_SYNC_VBI_VBLANK(tv_mode->vblank_level));
  484.  
  485.     regmap_write(tv->regs, SUN4I_TVE_ACTIVE_LINE_REG,
  486.              SUN4I_TVE_ACTIVE_LINE(1440));
  487.  
  488.     /* Set composite chroma gain to 50 % */
  489.     regmap_write(tv->regs, SUN4I_TVE_CHROMA_REG,
  490.              SUN4I_TVE_CHROMA_COMP_GAIN_50);
  491.  
  492.     regmap_write(tv->regs, SUN4I_TVE_12C_REG,
  493.              SUN4I_TVE_12C_COMP_YUV_EN |
  494.              SUN4I_TVE_12C_NOTCH_WIDTH_WIDE);
  495.  
  496.     regmap_write(tv->regs, SUN4I_TVE_RESYNC_REG,
  497.              SUN4I_TVE_RESYNC_PIXEL(tv_mode->resync_params->pixel) |
  498.              SUN4I_TVE_RESYNC_LINE(tv_mode->resync_params->line) |
  499.              (tv_mode->resync_params->field ?
  500.               SUN4I_TVE_RESYNC_FIELD : 0));
  501.  
  502.     regmap_write(tv->regs, SUN4I_TVE_SLAVE_REG, 0);
  503. }
  504.  
  505. static struct drm_encoder_helper_funcs sun4i_tv_helper_funcs = {
  506.     .disable    = sun4i_tv_disable,
  507.     .enable     = sun4i_tv_enable,
  508.     .mode_set   = sun4i_tv_mode_set,
  509. };
  510.  
  511. static void sun4i_tv_destroy(struct drm_encoder *encoder)
  512. {
  513.     DRM_DEBUG_DRIVER("TVE: sun4i_tv_destroy\n");
  514.    
  515.     drm_encoder_cleanup(encoder);
  516. }
  517.  
  518. static struct drm_encoder_funcs sun4i_tv_funcs = {
  519.     .destroy    = sun4i_tv_destroy,
  520. };
  521.  
  522. static int sun4i_tv_comp_get_modes(struct drm_connector *connector)
  523. {
  524.     int i;
  525.  
  526.     DRM_DEBUG_DRIVER("TVE: sun4i_tv_comp_get_modes\n");
  527.  
  528.     for (i = 0; i < ARRAY_SIZE(tv_modes); i++) {
  529.         struct drm_display_mode *mode;
  530.         const struct tv_mode *tv_mode = &tv_modes[i];
  531.  
  532.         mode = drm_mode_create(connector->dev);
  533.         if (!mode) {
  534.             DRM_ERROR("Failed to create a new display mode\n");
  535.             return 0;
  536.         }
  537.  
  538.         strcpy(mode->name, tv_mode->name);
  539.  
  540.         sun4i_tv_mode_to_drm_mode(tv_mode, mode);
  541.         drm_mode_probed_add(connector, mode);
  542.     }
  543.  
  544.     return i;
  545. }
  546.  
  547. static int sun4i_tv_comp_mode_valid(struct drm_connector *connector,
  548.                     struct drm_display_mode *mode)
  549. {
  550.     DRM_DEBUG_DRIVER("TVE: sun4i_tv_comp_mode_valid\n");
  551.    
  552.     /* TODO */
  553.     return MODE_OK;
  554. }
  555.  
  556. static struct drm_connector_helper_funcs sun4i_tv_comp_connector_helper_funcs = {
  557.     .get_modes  = sun4i_tv_comp_get_modes,
  558.     .mode_valid = sun4i_tv_comp_mode_valid,
  559. };
  560.  
  561. static void
  562. sun4i_tv_comp_connector_destroy(struct drm_connector *connector)
  563. {
  564.     DRM_DEBUG_DRIVER("TVE: sun4i_tv_comp_connector_destroy\n");
  565.  
  566.     drm_connector_cleanup(connector);
  567. }
  568.  
  569. static const struct drm_connector_funcs sun4i_tv_comp_connector_funcs = {
  570.     .fill_modes     = drm_helper_probe_single_connector_modes,
  571.     .destroy        = sun4i_tv_comp_connector_destroy,
  572.     .reset          = drm_atomic_helper_connector_reset,
  573.     .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
  574.     .atomic_destroy_state   = drm_atomic_helper_connector_destroy_state,
  575. };
  576.  
  577. static struct regmap_config sun4i_tv_regmap_config = {
  578.     .reg_bits   = 32,
  579.     .val_bits   = 32,
  580.     .reg_stride = 4,
  581.     .max_register   = SUN4I_TVE_WSS_DATA2_REG,
  582.     .name       = "tv-encoder",
  583. };
  584.  
  585. static int sun4i_tv_bind(struct device *dev, struct device *master,
  586.              void *data)
  587. {
  588.     struct platform_device *pdev = to_platform_device(dev);
  589.     struct drm_device *drm = data;
  590.     struct sun4i_drv *drv = drm->dev_private;
  591.     struct sun4i_tv *tv;
  592.     struct resource *res;
  593.     void __iomem *regs;
  594.     int ret;
  595.  
  596.     DRM_DEBUG_DRIVER("TVE: sun4i_tv_bind\n");
  597.  
  598.     tv = devm_kzalloc(dev, sizeof(*tv), GFP_KERNEL);
  599.     if (!tv)
  600.         return -ENOMEM;
  601.     tv->drv = drv;
  602.     dev_set_drvdata(dev, tv);
  603.  
  604.     tv->quirks = of_device_get_match_data(dev);
  605.     if (!tv->quirks)
  606.         return -EINVAL;
  607.  
  608.     res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  609.     regs = devm_ioremap_resource(dev, res);
  610.     if (IS_ERR(regs)) {
  611.         dev_err(dev, "Couldn't map the TV encoder registers\n");
  612.         return PTR_ERR(regs);
  613.     }
  614.  
  615.     tv->regs = devm_regmap_init_mmio(dev, regs,
  616.                      &sun4i_tv_regmap_config);
  617.     if (IS_ERR(tv->regs)) {
  618.         dev_err(dev, "Couldn't create the TV encoder regmap\n");
  619.         return PTR_ERR(tv->regs);
  620.     }
  621.  
  622.     tv->reset = devm_reset_control_get(dev, NULL);
  623.     if (IS_ERR(tv->reset)) {
  624.         dev_err(dev, "Couldn't get our reset line\n");
  625.         return PTR_ERR(tv->reset);
  626.     }
  627.  
  628.     ret = reset_control_deassert(tv->reset);
  629.     if (ret) {
  630.         dev_err(dev, "Couldn't deassert our reset line\n");
  631.         return ret;
  632.     }
  633.  
  634.     tv->clk = devm_clk_get(dev, NULL);
  635.     if (IS_ERR(tv->clk)) {
  636.         dev_err(dev, "Couldn't get the TV encoder clock\n");
  637.         ret = PTR_ERR(tv->clk);
  638.         goto err_assert_reset;
  639.     }
  640.     clk_prepare_enable(tv->clk);
  641.  
  642.     drm_encoder_helper_add(&tv->encoder,
  643.                    &sun4i_tv_helper_funcs);
  644.     ret = drm_encoder_init(drm,
  645.                    &tv->encoder,
  646.                    &sun4i_tv_funcs,
  647.                    DRM_MODE_ENCODER_TVDAC,
  648.                    NULL);
  649.     if (ret) {
  650.         dev_err(dev, "Couldn't initialise the TV encoder\n");
  651.         goto err_disable_clk;
  652.     }
  653.  
  654.     tv->encoder.possible_crtcs = drm_of_find_possible_crtcs(drm,
  655.                                 dev->of_node);
  656.     if (!tv->encoder.possible_crtcs) {
  657.         ret = -EPROBE_DEFER;
  658.         goto err_disable_clk;
  659.     }
  660.  
  661.     drm_connector_helper_add(&tv->connector,
  662.                  &sun4i_tv_comp_connector_helper_funcs);
  663.     ret = drm_connector_init(drm, &tv->connector,
  664.                  &sun4i_tv_comp_connector_funcs,
  665.                  DRM_MODE_CONNECTOR_Composite);
  666.     if (ret) {
  667.         dev_err(dev,
  668.             "Couldn't initialise the Composite connector\n");
  669.         goto err_cleanup_connector;
  670.     }
  671.     tv->connector.interlace_allowed = true;
  672.  
  673.     drm_mode_connector_attach_encoder(&tv->connector, &tv->encoder);
  674.  
  675.     return 0;
  676.  
  677. err_cleanup_connector:
  678.     drm_encoder_cleanup(&tv->encoder);
  679. err_disable_clk:
  680.     clk_disable_unprepare(tv->clk);
  681. err_assert_reset:
  682.     reset_control_assert(tv->reset);
  683.     return ret;
  684. }
  685.  
  686. static void sun4i_tv_unbind(struct device *dev, struct device *master,
  687.                 void *data)
  688. {
  689.     struct sun4i_tv *tv = dev_get_drvdata(dev);
  690.     DRM_DEBUG_DRIVER("TVE: sun4i_tv_unbind\n");
  691.  
  692.     drm_connector_cleanup(&tv->connector);
  693.     drm_encoder_cleanup(&tv->encoder);
  694.     clk_disable_unprepare(tv->clk);
  695. }
  696.  
  697. static const struct component_ops sun4i_tv_ops = {
  698.     .bind   = sun4i_tv_bind,
  699.     .unbind = sun4i_tv_unbind,
  700. };
  701.  
  702. static int sun4i_tv_probe(struct platform_device *pdev)
  703. {
  704.     DRM_DEBUG_DRIVER("TVE: sun4i_tv_probe\n");
  705.     return component_add(&pdev->dev, &sun4i_tv_ops);
  706. }
  707.  
  708. static int sun4i_tv_remove(struct platform_device *pdev)
  709. {
  710.     DRM_DEBUG_DRIVER("TVE: sun4i_tv_remove\n");
  711.     component_del(&pdev->dev, &sun4i_tv_ops);
  712.  
  713.     return 0;
  714. }
  715.  
  716. static const struct sun4i_tv_quirks sun4i_a10_tv_quirks = {
  717.     /* Nothing special */
  718. };
  719.  
  720. static const struct sun4i_tv_quirks sun8i_h3_tv_quirks = {
  721.     .fixed_divider = 16,
  722. };
  723.  
  724. static const struct of_device_id sun4i_tv_of_table[] = {
  725.     {
  726.         .compatible = "allwinner,sun4i-a10-tv-encoder",
  727.         .data = &sun4i_a10_tv_quirks,
  728.     },
  729.     {
  730.         .compatible = "allwinner,sun8i-h3-tv-encoder",
  731.         .data = &sun8i_h3_tv_quirks,
  732.     },
  733.     { }
  734. };
  735. MODULE_DEVICE_TABLE(of, sun4i_tv_of_table);
  736.  
  737. static struct platform_driver sun4i_tv_platform_driver = {
  738.     .probe      = sun4i_tv_probe,
  739.     .remove     = sun4i_tv_remove,
  740.     .driver     = {
  741.         .name       = "sun4i-tve",
  742.         .of_match_table = sun4i_tv_of_table,
  743.     },
  744. };
  745. module_platform_driver(sun4i_tv_platform_driver);
  746.  
  747. MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
  748. MODULE_DESCRIPTION("Allwinner A10 TV Encoder Driver");
  749. MODULE_LICENSE("GPL");
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement