sun4i_tcon.c 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Copyright (C) 2015 Free Electrons
  4. * Copyright (C) 2015 NextThing Co
  5. *
  6. * Maxime Ripard <maxime.ripard@free-electrons.com>
  7. */
  8. #include <linux/component.h>
  9. #include <linux/ioport.h>
  10. #include <linux/media-bus-format.h>
  11. #include <linux/module.h>
  12. #include <linux/of.h>
  13. #include <linux/of_platform.h>
  14. #include <linux/platform_device.h>
  15. #include <linux/regmap.h>
  16. #include <linux/reset.h>
  17. #include <drm/drm_atomic_helper.h>
  18. #include <drm/drm_bridge.h>
  19. #include <drm/drm_connector.h>
  20. #include <drm/drm_crtc.h>
  21. #include <drm/drm_encoder.h>
  22. #include <drm/drm_modes.h>
  23. #include <drm/drm_of.h>
  24. #include <drm/drm_panel.h>
  25. #include <drm/drm_print.h>
  26. #include <drm/drm_probe_helper.h>
  27. #include <drm/drm_vblank.h>
  28. #include <uapi/drm/drm_mode.h>
  29. #include "sun4i_crtc.h"
  30. #include "sun4i_drv.h"
  31. #include "sun4i_lvds.h"
  32. #include "sun4i_rgb.h"
  33. #include "sun4i_tcon.h"
  34. #include "sun6i_mipi_dsi.h"
  35. #include "sun4i_tcon_dclk.h"
  36. #include "sun8i_tcon_top.h"
  37. #include "sunxi_engine.h"
  38. static struct drm_connector *sun4i_tcon_get_connector(const struct drm_encoder *encoder)
  39. {
  40. struct drm_connector *connector;
  41. struct drm_connector_list_iter iter;
  42. drm_connector_list_iter_begin(encoder->dev, &iter);
  43. drm_for_each_connector_iter(connector, &iter)
  44. if (connector->encoder == encoder) {
  45. drm_connector_list_iter_end(&iter);
  46. return connector;
  47. }
  48. drm_connector_list_iter_end(&iter);
  49. return NULL;
  50. }
  51. static int sun4i_tcon_get_pixel_depth(const struct drm_encoder *encoder)
  52. {
  53. struct drm_connector *connector;
  54. struct drm_display_info *info;
  55. connector = sun4i_tcon_get_connector(encoder);
  56. if (!connector)
  57. return -EINVAL;
  58. info = &connector->display_info;
  59. if (info->num_bus_formats != 1)
  60. return -EINVAL;
  61. switch (info->bus_formats[0]) {
  62. case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
  63. return 18;
  64. case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:
  65. case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG:
  66. return 24;
  67. }
  68. return -EINVAL;
  69. }
  70. static void sun4i_tcon_channel_set_status(struct sun4i_tcon *tcon, int channel,
  71. bool enabled)
  72. {
  73. struct clk *clk;
  74. switch (channel) {
  75. case 0:
  76. WARN_ON(!tcon->quirks->has_channel_0);
  77. regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG,
  78. SUN4I_TCON0_CTL_TCON_ENABLE,
  79. enabled ? SUN4I_TCON0_CTL_TCON_ENABLE : 0);
  80. clk = tcon->dclk;
  81. break;
  82. case 1:
  83. WARN_ON(!tcon->quirks->has_channel_1);
  84. regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG,
  85. SUN4I_TCON1_CTL_TCON_ENABLE,
  86. enabled ? SUN4I_TCON1_CTL_TCON_ENABLE : 0);
  87. clk = tcon->sclk1;
  88. break;
  89. default:
  90. DRM_WARN("Unknown channel... doing nothing\n");
  91. return;
  92. }
  93. if (enabled) {
  94. clk_prepare_enable(clk);
  95. clk_rate_exclusive_get(clk);
  96. } else {
  97. clk_rate_exclusive_put(clk);
  98. clk_disable_unprepare(clk);
  99. }
  100. }
  101. static void sun4i_tcon_setup_lvds_phy(struct sun4i_tcon *tcon,
  102. const struct drm_encoder *encoder)
  103. {
  104. regmap_write(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
  105. SUN4I_TCON0_LVDS_ANA0_CK_EN |
  106. SUN4I_TCON0_LVDS_ANA0_REG_V |
  107. SUN4I_TCON0_LVDS_ANA0_REG_C |
  108. SUN4I_TCON0_LVDS_ANA0_EN_MB |
  109. SUN4I_TCON0_LVDS_ANA0_PD |
  110. SUN4I_TCON0_LVDS_ANA0_DCHS);
  111. udelay(2); /* delay at least 1200 ns */
  112. regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA1_REG,
  113. SUN4I_TCON0_LVDS_ANA1_INIT,
  114. SUN4I_TCON0_LVDS_ANA1_INIT);
  115. udelay(1); /* delay at least 120 ns */
  116. regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA1_REG,
  117. SUN4I_TCON0_LVDS_ANA1_UPDATE,
  118. SUN4I_TCON0_LVDS_ANA1_UPDATE);
  119. regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
  120. SUN4I_TCON0_LVDS_ANA0_EN_MB,
  121. SUN4I_TCON0_LVDS_ANA0_EN_MB);
  122. }
  123. static void sun6i_tcon_setup_lvds_phy(struct sun4i_tcon *tcon,
  124. const struct drm_encoder *encoder)
  125. {
  126. u8 val;
  127. regmap_write(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
  128. SUN6I_TCON0_LVDS_ANA0_C(2) |
  129. SUN6I_TCON0_LVDS_ANA0_V(3) |
  130. SUN6I_TCON0_LVDS_ANA0_PD(2) |
  131. SUN6I_TCON0_LVDS_ANA0_EN_LDO);
  132. udelay(2);
  133. regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
  134. SUN6I_TCON0_LVDS_ANA0_EN_MB,
  135. SUN6I_TCON0_LVDS_ANA0_EN_MB);
  136. udelay(2);
  137. regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
  138. SUN6I_TCON0_LVDS_ANA0_EN_DRVC,
  139. SUN6I_TCON0_LVDS_ANA0_EN_DRVC);
  140. if (sun4i_tcon_get_pixel_depth(encoder) == 18)
  141. val = 7;
  142. else
  143. val = 0xf;
  144. regmap_write_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
  145. SUN6I_TCON0_LVDS_ANA0_EN_DRVD(0xf),
  146. SUN6I_TCON0_LVDS_ANA0_EN_DRVD(val));
  147. }
  148. static void sun4i_tcon_lvds_set_status(struct sun4i_tcon *tcon,
  149. const struct drm_encoder *encoder,
  150. bool enabled)
  151. {
  152. if (enabled) {
  153. regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_IF_REG,
  154. SUN4I_TCON0_LVDS_IF_EN,
  155. SUN4I_TCON0_LVDS_IF_EN);
  156. if (tcon->quirks->setup_lvds_phy)
  157. tcon->quirks->setup_lvds_phy(tcon, encoder);
  158. } else {
  159. regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_IF_REG,
  160. SUN4I_TCON0_LVDS_IF_EN, 0);
  161. }
  162. }
  163. void sun4i_tcon_set_status(struct sun4i_tcon *tcon,
  164. const struct drm_encoder *encoder,
  165. bool enabled)
  166. {
  167. bool is_lvds = false;
  168. int channel;
  169. switch (encoder->encoder_type) {
  170. case DRM_MODE_ENCODER_LVDS:
  171. is_lvds = true;
  172. fallthrough;
  173. case DRM_MODE_ENCODER_DSI:
  174. case DRM_MODE_ENCODER_NONE:
  175. channel = 0;
  176. break;
  177. case DRM_MODE_ENCODER_TMDS:
  178. case DRM_MODE_ENCODER_TVDAC:
  179. channel = 1;
  180. break;
  181. default:
  182. DRM_DEBUG_DRIVER("Unknown encoder type, doing nothing...\n");
  183. return;
  184. }
  185. if (is_lvds && !enabled)
  186. sun4i_tcon_lvds_set_status(tcon, encoder, false);
  187. regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
  188. SUN4I_TCON_GCTL_TCON_ENABLE,
  189. enabled ? SUN4I_TCON_GCTL_TCON_ENABLE : 0);
  190. if (is_lvds && enabled)
  191. sun4i_tcon_lvds_set_status(tcon, encoder, true);
  192. sun4i_tcon_channel_set_status(tcon, channel, enabled);
  193. }
  194. void sun4i_tcon_enable_vblank(struct sun4i_tcon *tcon, bool enable)
  195. {
  196. u32 mask, val = 0;
  197. DRM_DEBUG_DRIVER("%sabling VBLANK interrupt\n", enable ? "En" : "Dis");
  198. mask = SUN4I_TCON_GINT0_VBLANK_ENABLE(0) |
  199. SUN4I_TCON_GINT0_VBLANK_ENABLE(1) |
  200. SUN4I_TCON_GINT0_TCON0_TRI_FINISH_ENABLE;
  201. if (enable)
  202. val = mask;
  203. regmap_update_bits(tcon->regs, SUN4I_TCON_GINT0_REG, mask, val);
  204. }
  205. EXPORT_SYMBOL(sun4i_tcon_enable_vblank);
  206. /*
  207. * This function is a helper for TCON output muxing. The TCON output
  208. * muxing control register in earlier SoCs (without the TCON TOP block)
  209. * are located in TCON0. This helper returns a pointer to TCON0's
  210. * sun4i_tcon structure, or NULL if not found.
  211. */
  212. static struct sun4i_tcon *sun4i_get_tcon0(struct drm_device *drm)
  213. {
  214. struct sun4i_drv *drv = drm->dev_private;
  215. struct sun4i_tcon *tcon;
  216. list_for_each_entry(tcon, &drv->tcon_list, list)
  217. if (tcon->id == 0)
  218. return tcon;
  219. dev_warn(drm->dev,
  220. "TCON0 not found, display output muxing may not work\n");
  221. return NULL;
  222. }
  223. static void sun4i_tcon_set_mux(struct sun4i_tcon *tcon, int channel,
  224. const struct drm_encoder *encoder)
  225. {
  226. int ret = -ENOTSUPP;
  227. if (tcon->quirks->set_mux)
  228. ret = tcon->quirks->set_mux(tcon, encoder);
  229. DRM_DEBUG_DRIVER("Muxing encoder %s to CRTC %s: %d\n",
  230. encoder->name, encoder->crtc->name, ret);
  231. }
  232. static int sun4i_tcon_get_clk_delay(const struct drm_display_mode *mode,
  233. int channel)
  234. {
  235. int delay = mode->vtotal - mode->vdisplay;
  236. if (mode->flags & DRM_MODE_FLAG_INTERLACE)
  237. delay /= 2;
  238. if (channel == 1)
  239. delay -= 2;
  240. delay = min(delay, 30);
  241. DRM_DEBUG_DRIVER("TCON %d clock delay %u\n", channel, delay);
  242. return delay;
  243. }
  244. static void sun4i_tcon0_mode_set_dithering(struct sun4i_tcon *tcon,
  245. const struct drm_connector *connector)
  246. {
  247. u32 bus_format = 0;
  248. u32 val = 0;
  249. /* XXX Would this ever happen? */
  250. if (!connector)
  251. return;
  252. /*
  253. * FIXME: Undocumented bits
  254. *
  255. * The whole dithering process and these parameters are not
  256. * explained in the vendor documents or BSP kernel code.
  257. */
  258. regmap_write(tcon->regs, SUN4I_TCON0_FRM_SEED_PR_REG, 0x11111111);
  259. regmap_write(tcon->regs, SUN4I_TCON0_FRM_SEED_PG_REG, 0x11111111);
  260. regmap_write(tcon->regs, SUN4I_TCON0_FRM_SEED_PB_REG, 0x11111111);
  261. regmap_write(tcon->regs, SUN4I_TCON0_FRM_SEED_LR_REG, 0x11111111);
  262. regmap_write(tcon->regs, SUN4I_TCON0_FRM_SEED_LG_REG, 0x11111111);
  263. regmap_write(tcon->regs, SUN4I_TCON0_FRM_SEED_LB_REG, 0x11111111);
  264. regmap_write(tcon->regs, SUN4I_TCON0_FRM_TBL0_REG, 0x01010000);
  265. regmap_write(tcon->regs, SUN4I_TCON0_FRM_TBL1_REG, 0x15151111);
  266. regmap_write(tcon->regs, SUN4I_TCON0_FRM_TBL2_REG, 0x57575555);
  267. regmap_write(tcon->regs, SUN4I_TCON0_FRM_TBL3_REG, 0x7f7f7777);
  268. /* Do dithering if panel only supports 6 bits per color */
  269. if (connector->display_info.bpc == 6)
  270. val |= SUN4I_TCON0_FRM_CTL_EN;
  271. if (connector->display_info.num_bus_formats == 1)
  272. bus_format = connector->display_info.bus_formats[0];
  273. /* Check the connection format */
  274. switch (bus_format) {
  275. case MEDIA_BUS_FMT_RGB565_1X16:
  276. /* R and B components are only 5 bits deep */
  277. val |= SUN4I_TCON0_FRM_CTL_MODE_R;
  278. val |= SUN4I_TCON0_FRM_CTL_MODE_B;
  279. fallthrough;
  280. case MEDIA_BUS_FMT_RGB666_1X18:
  281. case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
  282. /* Fall through: enable dithering */
  283. val |= SUN4I_TCON0_FRM_CTL_EN;
  284. break;
  285. }
  286. /* Write dithering settings */
  287. regmap_write(tcon->regs, SUN4I_TCON_FRM_CTL_REG, val);
  288. }
  289. static void sun4i_tcon0_mode_set_cpu(struct sun4i_tcon *tcon,
  290. const struct drm_encoder *encoder,
  291. const struct drm_display_mode *mode)
  292. {
  293. /* TODO support normal CPU interface modes */
  294. struct sun6i_dsi *dsi = encoder_to_sun6i_dsi(encoder);
  295. struct mipi_dsi_device *device = dsi->device;
  296. u8 bpp = mipi_dsi_pixel_format_to_bpp(device->format);
  297. u8 lanes = device->lanes;
  298. u32 block_space, start_delay;
  299. u32 tcon_div;
  300. /*
  301. * dclk is required to run at 1/4 the DSI per-lane bit rate.
  302. */
  303. tcon->dclk_min_div = SUN6I_DSI_TCON_DIV;
  304. tcon->dclk_max_div = SUN6I_DSI_TCON_DIV;
  305. clk_set_rate(tcon->dclk, mode->crtc_clock * 1000 * (bpp / lanes)
  306. / SUN6I_DSI_TCON_DIV);
  307. /* Set the resolution */
  308. regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG,
  309. SUN4I_TCON0_BASIC0_X(mode->crtc_hdisplay) |
  310. SUN4I_TCON0_BASIC0_Y(mode->crtc_vdisplay));
  311. /* Set dithering if needed */
  312. sun4i_tcon0_mode_set_dithering(tcon, sun4i_tcon_get_connector(encoder));
  313. regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG,
  314. SUN4I_TCON0_CTL_IF_MASK,
  315. SUN4I_TCON0_CTL_IF_8080);
  316. regmap_write(tcon->regs, SUN4I_TCON_ECC_FIFO_REG,
  317. SUN4I_TCON_ECC_FIFO_EN);
  318. regmap_write(tcon->regs, SUN4I_TCON0_CPU_IF_REG,
  319. SUN4I_TCON0_CPU_IF_MODE_DSI |
  320. SUN4I_TCON0_CPU_IF_TRI_FIFO_FLUSH |
  321. SUN4I_TCON0_CPU_IF_TRI_FIFO_EN |
  322. SUN4I_TCON0_CPU_IF_TRI_EN);
  323. /*
  324. * This looks suspicious, but it works...
  325. *
  326. * The datasheet says that this should be set higher than 20 *
  327. * pixel cycle, but it's not clear what a pixel cycle is.
  328. */
  329. regmap_read(tcon->regs, SUN4I_TCON0_DCLK_REG, &tcon_div);
  330. tcon_div &= GENMASK(6, 0);
  331. block_space = mode->htotal * bpp / (tcon_div * lanes);
  332. block_space -= mode->hdisplay + 40;
  333. regmap_write(tcon->regs, SUN4I_TCON0_CPU_TRI0_REG,
  334. SUN4I_TCON0_CPU_TRI0_BLOCK_SPACE(block_space) |
  335. SUN4I_TCON0_CPU_TRI0_BLOCK_SIZE(mode->hdisplay));
  336. regmap_write(tcon->regs, SUN4I_TCON0_CPU_TRI1_REG,
  337. SUN4I_TCON0_CPU_TRI1_BLOCK_NUM(mode->vdisplay));
  338. start_delay = (mode->crtc_vtotal - mode->crtc_vdisplay - 10 - 1);
  339. start_delay = start_delay * mode->crtc_htotal * 149;
  340. start_delay = start_delay / (mode->crtc_clock / 1000) / 8;
  341. regmap_write(tcon->regs, SUN4I_TCON0_CPU_TRI2_REG,
  342. SUN4I_TCON0_CPU_TRI2_TRANS_START_SET(10) |
  343. SUN4I_TCON0_CPU_TRI2_START_DELAY(start_delay));
  344. /*
  345. * The Allwinner BSP has a comment that the period should be
  346. * the display clock * 15, but uses an hardcoded 3000...
  347. */
  348. regmap_write(tcon->regs, SUN4I_TCON_SAFE_PERIOD_REG,
  349. SUN4I_TCON_SAFE_PERIOD_NUM(3000) |
  350. SUN4I_TCON_SAFE_PERIOD_MODE(3));
  351. /* Enable the output on the pins */
  352. regmap_write(tcon->regs, SUN4I_TCON0_IO_TRI_REG,
  353. 0xe0000000);
  354. }
  355. static void sun4i_tcon0_mode_set_lvds(struct sun4i_tcon *tcon,
  356. const struct drm_encoder *encoder,
  357. const struct drm_display_mode *mode)
  358. {
  359. unsigned int bp;
  360. u8 clk_delay;
  361. u32 reg, val = 0;
  362. WARN_ON(!tcon->quirks->has_channel_0);
  363. tcon->dclk_min_div = 7;
  364. tcon->dclk_max_div = 7;
  365. clk_set_rate(tcon->dclk, mode->crtc_clock * 1000);
  366. /* Set the resolution */
  367. regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG,
  368. SUN4I_TCON0_BASIC0_X(mode->crtc_hdisplay) |
  369. SUN4I_TCON0_BASIC0_Y(mode->crtc_vdisplay));
  370. /* Set dithering if needed */
  371. sun4i_tcon0_mode_set_dithering(tcon, sun4i_tcon_get_connector(encoder));
  372. /* Adjust clock delay */
  373. clk_delay = sun4i_tcon_get_clk_delay(mode, 0);
  374. regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG,
  375. SUN4I_TCON0_CTL_CLK_DELAY_MASK,
  376. SUN4I_TCON0_CTL_CLK_DELAY(clk_delay));
  377. /*
  378. * This is called a backporch in the register documentation,
  379. * but it really is the back porch + hsync
  380. */
  381. bp = mode->crtc_htotal - mode->crtc_hsync_start;
  382. DRM_DEBUG_DRIVER("Setting horizontal total %d, backporch %d\n",
  383. mode->crtc_htotal, bp);
  384. /* Set horizontal display timings */
  385. regmap_write(tcon->regs, SUN4I_TCON0_BASIC1_REG,
  386. SUN4I_TCON0_BASIC1_H_TOTAL(mode->htotal) |
  387. SUN4I_TCON0_BASIC1_H_BACKPORCH(bp));
  388. /*
  389. * This is called a backporch in the register documentation,
  390. * but it really is the back porch + hsync
  391. */
  392. bp = mode->crtc_vtotal - mode->crtc_vsync_start;
  393. DRM_DEBUG_DRIVER("Setting vertical total %d, backporch %d\n",
  394. mode->crtc_vtotal, bp);
  395. /* Set vertical display timings */
  396. regmap_write(tcon->regs, SUN4I_TCON0_BASIC2_REG,
  397. SUN4I_TCON0_BASIC2_V_TOTAL(mode->crtc_vtotal * 2) |
  398. SUN4I_TCON0_BASIC2_V_BACKPORCH(bp));
  399. reg = SUN4I_TCON0_LVDS_IF_CLK_SEL_TCON0;
  400. if (sun4i_tcon_get_pixel_depth(encoder) == 24)
  401. reg |= SUN4I_TCON0_LVDS_IF_BITWIDTH_24BITS;
  402. else
  403. reg |= SUN4I_TCON0_LVDS_IF_BITWIDTH_18BITS;
  404. regmap_write(tcon->regs, SUN4I_TCON0_LVDS_IF_REG, reg);
  405. /* Setup the polarity of the various signals */
  406. if (!(mode->flags & DRM_MODE_FLAG_PHSYNC))
  407. val |= SUN4I_TCON0_IO_POL_HSYNC_POSITIVE;
  408. if (!(mode->flags & DRM_MODE_FLAG_PVSYNC))
  409. val |= SUN4I_TCON0_IO_POL_VSYNC_POSITIVE;
  410. regmap_write(tcon->regs, SUN4I_TCON0_IO_POL_REG, val);
  411. /* Map output pins to channel 0 */
  412. regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
  413. SUN4I_TCON_GCTL_IOMAP_MASK,
  414. SUN4I_TCON_GCTL_IOMAP_TCON0);
  415. /* Enable the output on the pins */
  416. regmap_write(tcon->regs, SUN4I_TCON0_IO_TRI_REG, 0xe0000000);
  417. }
  418. static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon,
  419. const struct drm_encoder *encoder,
  420. const struct drm_display_mode *mode)
  421. {
  422. struct drm_connector *connector = sun4i_tcon_get_connector(encoder);
  423. const struct drm_display_info *info = &connector->display_info;
  424. unsigned int bp, hsync, vsync;
  425. u8 clk_delay;
  426. u32 val = 0;
  427. WARN_ON(!tcon->quirks->has_channel_0);
  428. tcon->dclk_min_div = tcon->quirks->dclk_min_div;
  429. tcon->dclk_max_div = 127;
  430. clk_set_rate(tcon->dclk, mode->crtc_clock * 1000);
  431. /* Set the resolution */
  432. regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG,
  433. SUN4I_TCON0_BASIC0_X(mode->crtc_hdisplay) |
  434. SUN4I_TCON0_BASIC0_Y(mode->crtc_vdisplay));
  435. /* Set dithering if needed */
  436. sun4i_tcon0_mode_set_dithering(tcon, connector);
  437. /* Adjust clock delay */
  438. clk_delay = sun4i_tcon_get_clk_delay(mode, 0);
  439. regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG,
  440. SUN4I_TCON0_CTL_CLK_DELAY_MASK,
  441. SUN4I_TCON0_CTL_CLK_DELAY(clk_delay));
  442. /*
  443. * This is called a backporch in the register documentation,
  444. * but it really is the back porch + hsync
  445. */
  446. bp = mode->crtc_htotal - mode->crtc_hsync_start;
  447. DRM_DEBUG_DRIVER("Setting horizontal total %d, backporch %d\n",
  448. mode->crtc_htotal, bp);
  449. /* Set horizontal display timings */
  450. regmap_write(tcon->regs, SUN4I_TCON0_BASIC1_REG,
  451. SUN4I_TCON0_BASIC1_H_TOTAL(mode->crtc_htotal) |
  452. SUN4I_TCON0_BASIC1_H_BACKPORCH(bp));
  453. /*
  454. * This is called a backporch in the register documentation,
  455. * but it really is the back porch + hsync
  456. */
  457. bp = mode->crtc_vtotal - mode->crtc_vsync_start;
  458. DRM_DEBUG_DRIVER("Setting vertical total %d, backporch %d\n",
  459. mode->crtc_vtotal, bp);
  460. /* Set vertical display timings */
  461. regmap_write(tcon->regs, SUN4I_TCON0_BASIC2_REG,
  462. SUN4I_TCON0_BASIC2_V_TOTAL(mode->crtc_vtotal * 2) |
  463. SUN4I_TCON0_BASIC2_V_BACKPORCH(bp));
  464. /* Set Hsync and Vsync length */
  465. hsync = mode->crtc_hsync_end - mode->crtc_hsync_start;
  466. vsync = mode->crtc_vsync_end - mode->crtc_vsync_start;
  467. DRM_DEBUG_DRIVER("Setting HSYNC %d, VSYNC %d\n", hsync, vsync);
  468. regmap_write(tcon->regs, SUN4I_TCON0_BASIC3_REG,
  469. SUN4I_TCON0_BASIC3_V_SYNC(vsync) |
  470. SUN4I_TCON0_BASIC3_H_SYNC(hsync));
  471. /* Setup the polarity of the various signals */
  472. if (mode->flags & DRM_MODE_FLAG_PHSYNC)
  473. val |= SUN4I_TCON0_IO_POL_HSYNC_POSITIVE;
  474. if (mode->flags & DRM_MODE_FLAG_PVSYNC)
  475. val |= SUN4I_TCON0_IO_POL_VSYNC_POSITIVE;
  476. if (info->bus_flags & DRM_BUS_FLAG_DE_LOW)
  477. val |= SUN4I_TCON0_IO_POL_DE_NEGATIVE;
  478. if (info->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE)
  479. val |= SUN4I_TCON0_IO_POL_DCLK_DRIVE_NEGEDGE;
  480. regmap_update_bits(tcon->regs, SUN4I_TCON0_IO_POL_REG,
  481. SUN4I_TCON0_IO_POL_HSYNC_POSITIVE |
  482. SUN4I_TCON0_IO_POL_VSYNC_POSITIVE |
  483. SUN4I_TCON0_IO_POL_DCLK_DRIVE_NEGEDGE |
  484. SUN4I_TCON0_IO_POL_DE_NEGATIVE,
  485. val);
  486. /* Map output pins to channel 0 */
  487. regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
  488. SUN4I_TCON_GCTL_IOMAP_MASK,
  489. SUN4I_TCON_GCTL_IOMAP_TCON0);
  490. /* Enable the output on the pins */
  491. regmap_write(tcon->regs, SUN4I_TCON0_IO_TRI_REG, 0);
  492. }
  493. static void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon,
  494. const struct drm_display_mode *mode)
  495. {
  496. unsigned int bp, hsync, vsync, vtotal;
  497. u8 clk_delay;
  498. u32 val;
  499. WARN_ON(!tcon->quirks->has_channel_1);
  500. /* Configure the dot clock */
  501. clk_set_rate(tcon->sclk1, mode->crtc_clock * 1000);
  502. /* Adjust clock delay */
  503. clk_delay = sun4i_tcon_get_clk_delay(mode, 1);
  504. regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG,
  505. SUN4I_TCON1_CTL_CLK_DELAY_MASK,
  506. SUN4I_TCON1_CTL_CLK_DELAY(clk_delay));
  507. /* Set interlaced mode */
  508. if (mode->flags & DRM_MODE_FLAG_INTERLACE)
  509. val = SUN4I_TCON1_CTL_INTERLACE_ENABLE;
  510. else
  511. val = 0;
  512. regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG,
  513. SUN4I_TCON1_CTL_INTERLACE_ENABLE,
  514. val);
  515. /* Set the input resolution */
  516. regmap_write(tcon->regs, SUN4I_TCON1_BASIC0_REG,
  517. SUN4I_TCON1_BASIC0_X(mode->crtc_hdisplay) |
  518. SUN4I_TCON1_BASIC0_Y(mode->crtc_vdisplay));
  519. /* Set the upscaling resolution */
  520. regmap_write(tcon->regs, SUN4I_TCON1_BASIC1_REG,
  521. SUN4I_TCON1_BASIC1_X(mode->crtc_hdisplay) |
  522. SUN4I_TCON1_BASIC1_Y(mode->crtc_vdisplay));
  523. /* Set the output resolution */
  524. regmap_write(tcon->regs, SUN4I_TCON1_BASIC2_REG,
  525. SUN4I_TCON1_BASIC2_X(mode->crtc_hdisplay) |
  526. SUN4I_TCON1_BASIC2_Y(mode->crtc_vdisplay));
  527. /* Set horizontal display timings */
  528. bp = mode->crtc_htotal - mode->crtc_hsync_start;
  529. DRM_DEBUG_DRIVER("Setting horizontal total %d, backporch %d\n",
  530. mode->htotal, bp);
  531. regmap_write(tcon->regs, SUN4I_TCON1_BASIC3_REG,
  532. SUN4I_TCON1_BASIC3_H_TOTAL(mode->crtc_htotal) |
  533. SUN4I_TCON1_BASIC3_H_BACKPORCH(bp));
  534. bp = mode->crtc_vtotal - mode->crtc_vsync_start;
  535. DRM_DEBUG_DRIVER("Setting vertical total %d, backporch %d\n",
  536. mode->crtc_vtotal, bp);
  537. /*
  538. * The vertical resolution needs to be doubled in all
  539. * cases. We could use crtc_vtotal and always multiply by two,
  540. * but that leads to a rounding error in interlace when vtotal
  541. * is odd.
  542. *
  543. * This happens with TV's PAL for example, where vtotal will
  544. * be 625, crtc_vtotal 312, and thus crtc_vtotal * 2 will be
  545. * 624, which apparently confuses the hardware.
  546. *
  547. * To work around this, we will always use vtotal, and
  548. * multiply by two only if we're not in interlace.
  549. */
  550. vtotal = mode->vtotal;
  551. if (!(mode->flags & DRM_MODE_FLAG_INTERLACE))
  552. vtotal = vtotal * 2;
  553. /* Set vertical display timings */
  554. regmap_write(tcon->regs, SUN4I_TCON1_BASIC4_REG,
  555. SUN4I_TCON1_BASIC4_V_TOTAL(vtotal) |
  556. SUN4I_TCON1_BASIC4_V_BACKPORCH(bp));
  557. /* Set Hsync and Vsync length */
  558. hsync = mode->crtc_hsync_end - mode->crtc_hsync_start;
  559. vsync = mode->crtc_vsync_end - mode->crtc_vsync_start;
  560. DRM_DEBUG_DRIVER("Setting HSYNC %d, VSYNC %d\n", hsync, vsync);
  561. regmap_write(tcon->regs, SUN4I_TCON1_BASIC5_REG,
  562. SUN4I_TCON1_BASIC5_V_SYNC(vsync) |
  563. SUN4I_TCON1_BASIC5_H_SYNC(hsync));
  564. /* Setup the polarity of multiple signals */
  565. if (tcon->quirks->polarity_in_ch0) {
  566. val = 0;
  567. if (mode->flags & DRM_MODE_FLAG_PHSYNC)
  568. val |= SUN4I_TCON0_IO_POL_HSYNC_POSITIVE;
  569. if (mode->flags & DRM_MODE_FLAG_PVSYNC)
  570. val |= SUN4I_TCON0_IO_POL_VSYNC_POSITIVE;
  571. regmap_write(tcon->regs, SUN4I_TCON0_IO_POL_REG, val);
  572. } else {
  573. /* according to vendor driver, this bit must be always set */
  574. val = SUN4I_TCON1_IO_POL_UNKNOWN;
  575. if (mode->flags & DRM_MODE_FLAG_PHSYNC)
  576. val |= SUN4I_TCON1_IO_POL_HSYNC_POSITIVE;
  577. if (mode->flags & DRM_MODE_FLAG_PVSYNC)
  578. val |= SUN4I_TCON1_IO_POL_VSYNC_POSITIVE;
  579. regmap_write(tcon->regs, SUN4I_TCON1_IO_POL_REG, val);
  580. }
  581. /* Map output pins to channel 1 */
  582. regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
  583. SUN4I_TCON_GCTL_IOMAP_MASK,
  584. SUN4I_TCON_GCTL_IOMAP_TCON1);
  585. }
  586. void sun4i_tcon_mode_set(struct sun4i_tcon *tcon,
  587. const struct drm_encoder *encoder,
  588. const struct drm_display_mode *mode)
  589. {
  590. switch (encoder->encoder_type) {
  591. case DRM_MODE_ENCODER_DSI:
  592. /* DSI is tied to special case of CPU interface */
  593. sun4i_tcon0_mode_set_cpu(tcon, encoder, mode);
  594. break;
  595. case DRM_MODE_ENCODER_LVDS:
  596. sun4i_tcon0_mode_set_lvds(tcon, encoder, mode);
  597. break;
  598. case DRM_MODE_ENCODER_NONE:
  599. sun4i_tcon0_mode_set_rgb(tcon, encoder, mode);
  600. sun4i_tcon_set_mux(tcon, 0, encoder);
  601. break;
  602. case DRM_MODE_ENCODER_TVDAC:
  603. case DRM_MODE_ENCODER_TMDS:
  604. sun4i_tcon1_mode_set(tcon, mode);
  605. sun4i_tcon_set_mux(tcon, 1, encoder);
  606. break;
  607. default:
  608. DRM_DEBUG_DRIVER("Unknown encoder type, doing nothing...\n");
  609. }
  610. }
  611. EXPORT_SYMBOL(sun4i_tcon_mode_set);
  612. static void sun4i_tcon_finish_page_flip(struct drm_device *dev,
  613. struct sun4i_crtc *scrtc)
  614. {
  615. unsigned long flags;
  616. spin_lock_irqsave(&dev->event_lock, flags);
  617. if (scrtc->event) {
  618. drm_crtc_send_vblank_event(&scrtc->crtc, scrtc->event);
  619. drm_crtc_vblank_put(&scrtc->crtc);
  620. scrtc->event = NULL;
  621. }
  622. spin_unlock_irqrestore(&dev->event_lock, flags);
  623. }
  624. static irqreturn_t sun4i_tcon_handler(int irq, void *private)
  625. {
  626. struct sun4i_tcon *tcon = private;
  627. struct drm_device *drm = tcon->drm;
  628. struct sun4i_crtc *scrtc = tcon->crtc;
  629. struct sunxi_engine *engine = scrtc->engine;
  630. unsigned int status;
  631. regmap_read(tcon->regs, SUN4I_TCON_GINT0_REG, &status);
  632. if (!(status & (SUN4I_TCON_GINT0_VBLANK_INT(0) |
  633. SUN4I_TCON_GINT0_VBLANK_INT(1) |
  634. SUN4I_TCON_GINT0_TCON0_TRI_FINISH_INT)))
  635. return IRQ_NONE;
  636. drm_crtc_handle_vblank(&scrtc->crtc);
  637. sun4i_tcon_finish_page_flip(drm, scrtc);
  638. /* Acknowledge the interrupt */
  639. regmap_update_bits(tcon->regs, SUN4I_TCON_GINT0_REG,
  640. SUN4I_TCON_GINT0_VBLANK_INT(0) |
  641. SUN4I_TCON_GINT0_VBLANK_INT(1) |
  642. SUN4I_TCON_GINT0_TCON0_TRI_FINISH_INT,
  643. 0);
  644. if (engine->ops->vblank_quirk)
  645. engine->ops->vblank_quirk(engine);
  646. return IRQ_HANDLED;
  647. }
  648. static int sun4i_tcon_init_clocks(struct device *dev,
  649. struct sun4i_tcon *tcon)
  650. {
  651. tcon->clk = devm_clk_get_enabled(dev, "ahb");
  652. if (IS_ERR(tcon->clk)) {
  653. dev_err(dev, "Couldn't get the TCON bus clock\n");
  654. return PTR_ERR(tcon->clk);
  655. }
  656. if (tcon->quirks->has_channel_0) {
  657. tcon->sclk0 = devm_clk_get_enabled(dev, "tcon-ch0");
  658. if (IS_ERR(tcon->sclk0)) {
  659. dev_err(dev, "Couldn't get the TCON channel 0 clock\n");
  660. return PTR_ERR(tcon->sclk0);
  661. }
  662. }
  663. if (tcon->quirks->has_channel_1) {
  664. tcon->sclk1 = devm_clk_get(dev, "tcon-ch1");
  665. if (IS_ERR(tcon->sclk1)) {
  666. dev_err(dev, "Couldn't get the TCON channel 1 clock\n");
  667. return PTR_ERR(tcon->sclk1);
  668. }
  669. }
  670. return 0;
  671. }
  672. static int sun4i_tcon_init_irq(struct device *dev,
  673. struct sun4i_tcon *tcon)
  674. {
  675. struct platform_device *pdev = to_platform_device(dev);
  676. int irq, ret;
  677. irq = platform_get_irq(pdev, 0);
  678. if (irq < 0)
  679. return irq;
  680. ret = devm_request_irq(dev, irq, sun4i_tcon_handler, 0,
  681. dev_name(dev), tcon);
  682. if (ret) {
  683. dev_err(dev, "Couldn't request the IRQ\n");
  684. return ret;
  685. }
  686. return 0;
  687. }
  688. static const struct regmap_config sun4i_tcon_regmap_config = {
  689. .reg_bits = 32,
  690. .val_bits = 32,
  691. .reg_stride = 4,
  692. .max_register = 0x800,
  693. };
  694. static int sun4i_tcon_init_regmap(struct device *dev,
  695. struct sun4i_tcon *tcon)
  696. {
  697. struct platform_device *pdev = to_platform_device(dev);
  698. void __iomem *regs;
  699. regs = devm_platform_ioremap_resource(pdev, 0);
  700. if (IS_ERR(regs))
  701. return PTR_ERR(regs);
  702. tcon->regs = devm_regmap_init_mmio(dev, regs,
  703. &sun4i_tcon_regmap_config);
  704. if (IS_ERR(tcon->regs)) {
  705. dev_err(dev, "Couldn't create the TCON regmap\n");
  706. return PTR_ERR(tcon->regs);
  707. }
  708. /* Make sure the TCON is disabled and all IRQs are off */
  709. regmap_write(tcon->regs, SUN4I_TCON_GCTL_REG, 0);
  710. regmap_write(tcon->regs, SUN4I_TCON_GINT0_REG, 0);
  711. regmap_write(tcon->regs, SUN4I_TCON_GINT1_REG, 0);
  712. /* Disable IO lines and set them to tristate */
  713. regmap_write(tcon->regs, SUN4I_TCON0_IO_TRI_REG, ~0);
  714. regmap_write(tcon->regs, SUN4I_TCON1_IO_TRI_REG, ~0);
  715. return 0;
  716. }
  717. /*
  718. * On SoCs with the old display pipeline design (Display Engine 1.0),
  719. * the TCON is always tied to just one backend. Hence we can traverse
  720. * the of_graph upwards to find the backend our tcon is connected to,
  721. * and take its ID as our own.
  722. *
  723. * We can either identify backends from their compatible strings, which
  724. * means maintaining a large list of them. Or, since the backend is
  725. * registered and binded before the TCON, we can just go through the
  726. * list of registered backends and compare the device node.
  727. *
  728. * As the structures now store engines instead of backends, here this
  729. * function in fact searches the corresponding engine, and the ID is
  730. * requested via the get_id function of the engine.
  731. */
  732. static struct sunxi_engine *
  733. sun4i_tcon_find_engine_traverse(struct sun4i_drv *drv,
  734. struct device_node *node,
  735. u32 port_id)
  736. {
  737. struct device_node *port, *ep, *remote;
  738. struct sunxi_engine *engine = ERR_PTR(-EINVAL);
  739. u32 reg = 0;
  740. port = of_graph_get_port_by_id(node, port_id);
  741. if (!port)
  742. return ERR_PTR(-EINVAL);
  743. /*
  744. * This only works if there is only one path from the TCON
  745. * to any display engine. Otherwise the probe order of the
  746. * TCONs and display engines is not guaranteed. They may
  747. * either bind to the wrong one, or worse, bind to the same
  748. * one if additional checks are not done.
  749. *
  750. * Bail out if there are multiple input connections.
  751. */
  752. if (of_get_available_child_count(port) != 1)
  753. goto out_put_port;
  754. /* Get the first connection without specifying an ID */
  755. ep = of_get_next_available_child(port, NULL);
  756. if (!ep)
  757. goto out_put_port;
  758. remote = of_graph_get_remote_port_parent(ep);
  759. if (!remote)
  760. goto out_put_ep;
  761. /* does this node match any registered engines? */
  762. list_for_each_entry(engine, &drv->engine_list, list)
  763. if (remote == engine->node)
  764. goto out_put_remote;
  765. /*
  766. * According to device tree binding input ports have even id
  767. * number and output ports have odd id. Since component with
  768. * more than one input and one output (TCON TOP) exits, correct
  769. * remote input id has to be calculated by subtracting 1 from
  770. * remote output id. If this for some reason can't be done, 0
  771. * is used as input port id.
  772. */
  773. of_node_put(port);
  774. port = of_graph_get_remote_port(ep);
  775. if (!of_property_read_u32(port, "reg", &reg) && reg > 0)
  776. reg -= 1;
  777. /* keep looking through upstream ports */
  778. engine = sun4i_tcon_find_engine_traverse(drv, remote, reg);
  779. out_put_remote:
  780. of_node_put(remote);
  781. out_put_ep:
  782. of_node_put(ep);
  783. out_put_port:
  784. of_node_put(port);
  785. return engine;
  786. }
  787. /*
  788. * The device tree binding says that the remote endpoint ID of any
  789. * connection between components, up to and including the TCON, of
  790. * the display pipeline should be equal to the actual ID of the local
  791. * component. Thus we can look at any one of the input connections of
  792. * the TCONs, and use that connection's remote endpoint ID as our own.
  793. *
  794. * Since the user of this function already finds the input port,
  795. * the port is passed in directly without further checks.
  796. */
  797. static int sun4i_tcon_of_get_id_from_port(struct device_node *port)
  798. {
  799. struct device_node *ep;
  800. int ret = -EINVAL;
  801. /* try finding an upstream endpoint */
  802. for_each_available_child_of_node(port, ep) {
  803. struct device_node *remote;
  804. u32 reg;
  805. remote = of_graph_get_remote_endpoint(ep);
  806. if (!remote)
  807. continue;
  808. ret = of_property_read_u32(remote, "reg", &reg);
  809. if (ret)
  810. continue;
  811. ret = reg;
  812. }
  813. return ret;
  814. }
  815. /*
  816. * Once we know the TCON's id, we can look through the list of
  817. * engines to find a matching one. We assume all engines have
  818. * been probed and added to the list.
  819. */
  820. static struct sunxi_engine *sun4i_tcon_get_engine_by_id(struct sun4i_drv *drv,
  821. int id)
  822. {
  823. struct sunxi_engine *engine;
  824. list_for_each_entry(engine, &drv->engine_list, list)
  825. if (engine->id == id)
  826. return engine;
  827. return ERR_PTR(-EINVAL);
  828. }
  829. static bool sun4i_tcon_connected_to_tcon_top(struct device_node *node)
  830. {
  831. struct device_node *remote;
  832. bool ret = false;
  833. remote = of_graph_get_remote_node(node, 0, -1);
  834. if (remote) {
  835. ret = !!(IS_ENABLED(CONFIG_DRM_SUN8I_TCON_TOP) &&
  836. of_match_node(sun8i_tcon_top_of_table, remote));
  837. of_node_put(remote);
  838. }
  839. return ret;
  840. }
  841. static int sun4i_tcon_get_index(struct sun4i_drv *drv)
  842. {
  843. struct list_head *pos;
  844. int size = 0;
  845. /*
  846. * Because TCON is added to the list at the end of the probe
  847. * (after this function is called), index of the current TCON
  848. * will be same as current TCON list size.
  849. */
  850. list_for_each(pos, &drv->tcon_list)
  851. ++size;
  852. return size;
  853. }
  854. /*
  855. * On SoCs with the old display pipeline design (Display Engine 1.0),
  856. * we assumed the TCON was always tied to just one backend. However
  857. * this proved not to be the case. On the A31, the TCON can select
  858. * either backend as its source. On the A20 (and likely on the A10),
  859. * the backend can choose which TCON to output to.
  860. *
  861. * The device tree binding says that the remote endpoint ID of any
  862. * connection between components, up to and including the TCON, of
  863. * the display pipeline should be equal to the actual ID of the local
  864. * component. Thus we should be able to look at any one of the input
  865. * connections of the TCONs, and use that connection's remote endpoint
  866. * ID as our own.
  867. *
  868. * However the connections between the backend and TCON were assumed
  869. * to be always singular, and their endpoit IDs were all incorrectly
  870. * set to 0. This means for these old device trees, we cannot just look
  871. * up the remote endpoint ID of a TCON input endpoint. TCON1 would be
  872. * incorrectly identified as TCON0.
  873. *
  874. * This function first checks if the TCON node has 2 input endpoints.
  875. * If so, then the device tree is a corrected version, and it will use
  876. * sun4i_tcon_of_get_id() and sun4i_tcon_get_engine_by_id() from above
  877. * to fetch the ID and engine directly. If not, then it is likely an
  878. * old device trees, where the endpoint IDs were incorrect, but did not
  879. * have endpoint connections between the backend and TCON across
  880. * different display pipelines. It will fall back to the old method of
  881. * traversing the of_graph to try and find a matching engine by device
  882. * node.
  883. *
  884. * In the case of single display pipeline device trees, either method
  885. * works.
  886. */
  887. static struct sunxi_engine *sun4i_tcon_find_engine(struct sun4i_drv *drv,
  888. struct device_node *node)
  889. {
  890. struct device_node *port;
  891. struct sunxi_engine *engine;
  892. port = of_graph_get_port_by_id(node, 0);
  893. if (!port)
  894. return ERR_PTR(-EINVAL);
  895. /*
  896. * Is this a corrected device tree with cross pipeline
  897. * connections between the backend and TCON?
  898. */
  899. if (of_get_child_count(port) > 1) {
  900. int id;
  901. /*
  902. * When pipeline has the same number of TCONs and engines which
  903. * are represented by frontends/backends (DE1) or mixers (DE2),
  904. * we match them by their respective IDs. However, if pipeline
  905. * contains TCON TOP, chances are that there are either more
  906. * TCONs than engines (R40) or TCONs with non-consecutive ids.
  907. * (H6). In that case it's easier just use TCON index in list
  908. * as an id. That means that on R40, any 2 TCONs can be enabled
  909. * in DT out of 4 (there are 2 mixers). Due to the design of
  910. * TCON TOP, remaining 2 TCONs can't be connected to anything
  911. * anyway.
  912. */
  913. if (sun4i_tcon_connected_to_tcon_top(node))
  914. id = sun4i_tcon_get_index(drv);
  915. else
  916. id = sun4i_tcon_of_get_id_from_port(port);
  917. /* Get our engine by matching our ID */
  918. engine = sun4i_tcon_get_engine_by_id(drv, id);
  919. of_node_put(port);
  920. return engine;
  921. }
  922. /* Fallback to old method by traversing input endpoints */
  923. of_node_put(port);
  924. return sun4i_tcon_find_engine_traverse(drv, node, 0);
  925. }
  926. static int sun4i_tcon_bind(struct device *dev, struct device *master,
  927. void *data)
  928. {
  929. struct drm_device *drm = data;
  930. struct sun4i_drv *drv = drm->dev_private;
  931. struct sunxi_engine *engine;
  932. struct device_node *remote;
  933. struct sun4i_tcon *tcon;
  934. struct reset_control *edp_rstc;
  935. bool has_lvds_rst, has_lvds_alt, can_lvds;
  936. int ret;
  937. engine = sun4i_tcon_find_engine(drv, dev->of_node);
  938. if (IS_ERR(engine)) {
  939. dev_err(dev, "Couldn't find matching engine\n");
  940. return -EPROBE_DEFER;
  941. }
  942. tcon = devm_kzalloc(dev, sizeof(*tcon), GFP_KERNEL);
  943. if (!tcon)
  944. return -ENOMEM;
  945. dev_set_drvdata(dev, tcon);
  946. tcon->drm = drm;
  947. tcon->dev = dev;
  948. tcon->id = engine->id;
  949. tcon->quirks = of_device_get_match_data(dev);
  950. tcon->lcd_rst = devm_reset_control_get(dev, "lcd");
  951. if (IS_ERR(tcon->lcd_rst)) {
  952. dev_err(dev, "Couldn't get our reset line\n");
  953. return PTR_ERR(tcon->lcd_rst);
  954. }
  955. if (tcon->quirks->needs_edp_reset) {
  956. edp_rstc = devm_reset_control_get_shared(dev, "edp");
  957. if (IS_ERR(edp_rstc)) {
  958. dev_err(dev, "Couldn't get edp reset line\n");
  959. return PTR_ERR(edp_rstc);
  960. }
  961. ret = reset_control_deassert(edp_rstc);
  962. if (ret) {
  963. dev_err(dev, "Couldn't deassert edp reset line\n");
  964. return ret;
  965. }
  966. }
  967. /* Make sure our TCON is reset */
  968. ret = reset_control_reset(tcon->lcd_rst);
  969. if (ret) {
  970. dev_err(dev, "Couldn't deassert our reset line\n");
  971. return ret;
  972. }
  973. if (tcon->quirks->supports_lvds) {
  974. /*
  975. * This can only be made optional since we've had DT
  976. * nodes without the LVDS reset properties.
  977. *
  978. * If the property is missing, just disable LVDS, and
  979. * print a warning.
  980. */
  981. tcon->lvds_rst = devm_reset_control_get_optional(dev, "lvds");
  982. if (IS_ERR(tcon->lvds_rst)) {
  983. dev_err(dev, "Couldn't get our reset line\n");
  984. return PTR_ERR(tcon->lvds_rst);
  985. } else if (tcon->lvds_rst) {
  986. has_lvds_rst = true;
  987. reset_control_reset(tcon->lvds_rst);
  988. } else {
  989. has_lvds_rst = false;
  990. }
  991. /*
  992. * This can only be made optional since we've had DT
  993. * nodes without the LVDS reset properties.
  994. *
  995. * If the property is missing, just disable LVDS, and
  996. * print a warning.
  997. */
  998. if (tcon->quirks->has_lvds_alt) {
  999. tcon->lvds_pll = devm_clk_get(dev, "lvds-alt");
  1000. if (IS_ERR(tcon->lvds_pll)) {
  1001. if (PTR_ERR(tcon->lvds_pll) == -ENOENT) {
  1002. has_lvds_alt = false;
  1003. } else {
  1004. dev_err(dev, "Couldn't get the LVDS PLL\n");
  1005. return PTR_ERR(tcon->lvds_pll);
  1006. }
  1007. } else {
  1008. has_lvds_alt = true;
  1009. }
  1010. }
  1011. if (!has_lvds_rst ||
  1012. (tcon->quirks->has_lvds_alt && !has_lvds_alt)) {
  1013. dev_warn(dev, "Missing LVDS properties, Please upgrade your DT\n");
  1014. dev_warn(dev, "LVDS output disabled\n");
  1015. can_lvds = false;
  1016. } else {
  1017. can_lvds = true;
  1018. }
  1019. } else {
  1020. can_lvds = false;
  1021. }
  1022. ret = sun4i_tcon_init_clocks(dev, tcon);
  1023. if (ret) {
  1024. dev_err(dev, "Couldn't init our TCON clocks\n");
  1025. goto err_assert_reset;
  1026. }
  1027. ret = sun4i_tcon_init_regmap(dev, tcon);
  1028. if (ret) {
  1029. dev_err(dev, "Couldn't init our TCON regmap\n");
  1030. goto err_assert_reset;
  1031. }
  1032. if (tcon->quirks->has_channel_0) {
  1033. ret = sun4i_dclk_create(dev, tcon);
  1034. if (ret) {
  1035. dev_err(dev, "Couldn't create our TCON dot clock\n");
  1036. goto err_assert_reset;
  1037. }
  1038. }
  1039. ret = sun4i_tcon_init_irq(dev, tcon);
  1040. if (ret) {
  1041. dev_err(dev, "Couldn't init our TCON interrupts\n");
  1042. goto err_free_dclk;
  1043. }
  1044. tcon->crtc = sun4i_crtc_init(drm, engine, tcon);
  1045. if (IS_ERR(tcon->crtc)) {
  1046. dev_err(dev, "Couldn't create our CRTC\n");
  1047. ret = PTR_ERR(tcon->crtc);
  1048. goto err_free_dclk;
  1049. }
  1050. if (tcon->quirks->has_channel_0) {
  1051. /*
  1052. * If we have an LVDS panel connected to the TCON, we should
  1053. * just probe the LVDS connector. Otherwise, just probe RGB as
  1054. * we used to.
  1055. */
  1056. remote = of_graph_get_remote_node(dev->of_node, 1, 0);
  1057. if (of_device_is_compatible(remote, "panel-lvds"))
  1058. if (can_lvds)
  1059. ret = sun4i_lvds_init(drm, tcon);
  1060. else
  1061. ret = -EINVAL;
  1062. else
  1063. ret = sun4i_rgb_init(drm, tcon);
  1064. of_node_put(remote);
  1065. if (ret < 0)
  1066. goto err_free_dclk;
  1067. }
  1068. if (tcon->quirks->needs_de_be_mux) {
  1069. /*
  1070. * We assume there is no dynamic muxing of backends
  1071. * and TCONs, so we select the backend with same ID.
  1072. *
  1073. * While dynamic selection might be interesting, since
  1074. * the CRTC is tied to the TCON, while the layers are
  1075. * tied to the backends, this means, we will need to
  1076. * switch between groups of layers. There might not be
  1077. * a way to represent this constraint in DRM.
  1078. */
  1079. regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG,
  1080. SUN4I_TCON0_CTL_SRC_SEL_MASK,
  1081. tcon->id);
  1082. regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG,
  1083. SUN4I_TCON1_CTL_SRC_SEL_MASK,
  1084. tcon->id);
  1085. }
  1086. list_add_tail(&tcon->list, &drv->tcon_list);
  1087. return 0;
  1088. err_free_dclk:
  1089. if (tcon->quirks->has_channel_0)
  1090. sun4i_dclk_free(tcon);
  1091. err_assert_reset:
  1092. reset_control_assert(tcon->lcd_rst);
  1093. return ret;
  1094. }
  1095. static void sun4i_tcon_unbind(struct device *dev, struct device *master,
  1096. void *data)
  1097. {
  1098. struct sun4i_tcon *tcon = dev_get_drvdata(dev);
  1099. list_del(&tcon->list);
  1100. if (tcon->quirks->has_channel_0)
  1101. sun4i_dclk_free(tcon);
  1102. }
  1103. static const struct component_ops sun4i_tcon_ops = {
  1104. .bind = sun4i_tcon_bind,
  1105. .unbind = sun4i_tcon_unbind,
  1106. };
  1107. static int sun4i_tcon_probe(struct platform_device *pdev)
  1108. {
  1109. struct device_node *node = pdev->dev.of_node;
  1110. const struct sun4i_tcon_quirks *quirks;
  1111. struct drm_bridge *bridge;
  1112. struct drm_panel *panel;
  1113. int ret;
  1114. quirks = of_device_get_match_data(&pdev->dev);
  1115. /* panels and bridges are present only on TCONs with channel 0 */
  1116. if (quirks->has_channel_0) {
  1117. ret = drm_of_find_panel_or_bridge(node, 1, 0, &panel, &bridge);
  1118. if (ret == -EPROBE_DEFER)
  1119. return ret;
  1120. }
  1121. return component_add(&pdev->dev, &sun4i_tcon_ops);
  1122. }
  1123. static void sun4i_tcon_remove(struct platform_device *pdev)
  1124. {
  1125. component_del(&pdev->dev, &sun4i_tcon_ops);
  1126. }
  1127. /* platform specific TCON muxing callbacks */
  1128. static int sun4i_a10_tcon_set_mux(struct sun4i_tcon *tcon,
  1129. const struct drm_encoder *encoder)
  1130. {
  1131. struct sun4i_tcon *tcon0 = sun4i_get_tcon0(encoder->dev);
  1132. u32 shift;
  1133. if (!tcon0)
  1134. return -EINVAL;
  1135. switch (encoder->encoder_type) {
  1136. case DRM_MODE_ENCODER_TMDS:
  1137. /* HDMI */
  1138. shift = 8;
  1139. break;
  1140. default:
  1141. return -EINVAL;
  1142. }
  1143. regmap_update_bits(tcon0->regs, SUN4I_TCON_MUX_CTRL_REG,
  1144. 0x3 << shift, tcon->id << shift);
  1145. return 0;
  1146. }
  1147. static int sun5i_a13_tcon_set_mux(struct sun4i_tcon *tcon,
  1148. const struct drm_encoder *encoder)
  1149. {
  1150. u32 val;
  1151. if (encoder->encoder_type == DRM_MODE_ENCODER_TVDAC)
  1152. val = 1;
  1153. else
  1154. val = 0;
  1155. /*
  1156. * FIXME: Undocumented bits
  1157. */
  1158. return regmap_write(tcon->regs, SUN4I_TCON_MUX_CTRL_REG, val);
  1159. }
  1160. static int sun6i_tcon_set_mux(struct sun4i_tcon *tcon,
  1161. const struct drm_encoder *encoder)
  1162. {
  1163. struct sun4i_tcon *tcon0 = sun4i_get_tcon0(encoder->dev);
  1164. u32 shift;
  1165. if (!tcon0)
  1166. return -EINVAL;
  1167. switch (encoder->encoder_type) {
  1168. case DRM_MODE_ENCODER_TMDS:
  1169. /* HDMI */
  1170. shift = 8;
  1171. break;
  1172. default:
  1173. /* TODO A31 has MIPI DSI but A31s does not */
  1174. return -EINVAL;
  1175. }
  1176. regmap_update_bits(tcon0->regs, SUN4I_TCON_MUX_CTRL_REG,
  1177. 0x3 << shift, tcon->id << shift);
  1178. return 0;
  1179. }
  1180. static int sun8i_r40_tcon_tv_set_mux(struct sun4i_tcon *tcon,
  1181. const struct drm_encoder *encoder)
  1182. {
  1183. struct device_node *port, *remote;
  1184. struct platform_device *pdev;
  1185. int id, ret;
  1186. /* find TCON TOP platform device and TCON id */
  1187. port = of_graph_get_port_by_id(tcon->dev->of_node, 0);
  1188. if (!port)
  1189. return -EINVAL;
  1190. id = sun4i_tcon_of_get_id_from_port(port);
  1191. of_node_put(port);
  1192. remote = of_graph_get_remote_node(tcon->dev->of_node, 0, -1);
  1193. if (!remote)
  1194. return -EINVAL;
  1195. pdev = of_find_device_by_node(remote);
  1196. of_node_put(remote);
  1197. if (!pdev)
  1198. return -EINVAL;
  1199. if (IS_ENABLED(CONFIG_DRM_SUN8I_TCON_TOP) &&
  1200. encoder->encoder_type == DRM_MODE_ENCODER_TMDS) {
  1201. ret = sun8i_tcon_top_set_hdmi_src(&pdev->dev, id);
  1202. if (ret) {
  1203. put_device(&pdev->dev);
  1204. return ret;
  1205. }
  1206. }
  1207. if (IS_ENABLED(CONFIG_DRM_SUN8I_TCON_TOP)) {
  1208. ret = sun8i_tcon_top_de_config(&pdev->dev, tcon->id, id);
  1209. if (ret) {
  1210. put_device(&pdev->dev);
  1211. return ret;
  1212. }
  1213. }
  1214. return 0;
  1215. }
  1216. static const struct sun4i_tcon_quirks sun4i_a10_quirks = {
  1217. .has_channel_0 = true,
  1218. .has_channel_1 = true,
  1219. .dclk_min_div = 4,
  1220. .set_mux = sun4i_a10_tcon_set_mux,
  1221. };
  1222. static const struct sun4i_tcon_quirks sun5i_a13_quirks = {
  1223. .has_channel_0 = true,
  1224. .has_channel_1 = true,
  1225. .dclk_min_div = 4,
  1226. .set_mux = sun5i_a13_tcon_set_mux,
  1227. };
  1228. static const struct sun4i_tcon_quirks sun6i_a31_quirks = {
  1229. .has_channel_0 = true,
  1230. .has_channel_1 = true,
  1231. .has_lvds_alt = true,
  1232. .needs_de_be_mux = true,
  1233. .dclk_min_div = 1,
  1234. .set_mux = sun6i_tcon_set_mux,
  1235. };
  1236. static const struct sun4i_tcon_quirks sun6i_a31s_quirks = {
  1237. .has_channel_0 = true,
  1238. .has_channel_1 = true,
  1239. .needs_de_be_mux = true,
  1240. .dclk_min_div = 1,
  1241. };
  1242. static const struct sun4i_tcon_quirks sun7i_a20_tcon0_quirks = {
  1243. .supports_lvds = true,
  1244. .has_channel_0 = true,
  1245. .has_channel_1 = true,
  1246. .dclk_min_div = 4,
  1247. /* Same display pipeline structure as A10 */
  1248. .set_mux = sun4i_a10_tcon_set_mux,
  1249. .setup_lvds_phy = sun4i_tcon_setup_lvds_phy,
  1250. };
  1251. static const struct sun4i_tcon_quirks sun7i_a20_quirks = {
  1252. .has_channel_0 = true,
  1253. .has_channel_1 = true,
  1254. .dclk_min_div = 4,
  1255. /* Same display pipeline structure as A10 */
  1256. .set_mux = sun4i_a10_tcon_set_mux,
  1257. };
  1258. static const struct sun4i_tcon_quirks sun8i_a33_quirks = {
  1259. .has_channel_0 = true,
  1260. .has_lvds_alt = true,
  1261. .dclk_min_div = 1,
  1262. .setup_lvds_phy = sun6i_tcon_setup_lvds_phy,
  1263. .supports_lvds = true,
  1264. };
  1265. static const struct sun4i_tcon_quirks sun8i_a83t_lcd_quirks = {
  1266. .supports_lvds = true,
  1267. .has_channel_0 = true,
  1268. .dclk_min_div = 1,
  1269. .setup_lvds_phy = sun6i_tcon_setup_lvds_phy,
  1270. };
  1271. static const struct sun4i_tcon_quirks sun8i_a83t_tv_quirks = {
  1272. .has_channel_1 = true,
  1273. };
  1274. static const struct sun4i_tcon_quirks sun8i_r40_tv_quirks = {
  1275. .has_channel_1 = true,
  1276. .polarity_in_ch0 = true,
  1277. .set_mux = sun8i_r40_tcon_tv_set_mux,
  1278. };
  1279. static const struct sun4i_tcon_quirks sun8i_v3s_quirks = {
  1280. .has_channel_0 = true,
  1281. .dclk_min_div = 1,
  1282. };
  1283. static const struct sun4i_tcon_quirks sun9i_a80_tcon_lcd_quirks = {
  1284. .has_channel_0 = true,
  1285. .needs_edp_reset = true,
  1286. .dclk_min_div = 1,
  1287. };
  1288. static const struct sun4i_tcon_quirks sun9i_a80_tcon_tv_quirks = {
  1289. .has_channel_1 = true,
  1290. .needs_edp_reset = true,
  1291. };
  1292. static const struct sun4i_tcon_quirks sun20i_d1_lcd_quirks = {
  1293. .has_channel_0 = true,
  1294. .dclk_min_div = 1,
  1295. .set_mux = sun8i_r40_tcon_tv_set_mux,
  1296. };
  1297. /* sun4i_drv uses this list to check if a device node is a TCON */
  1298. const struct of_device_id sun4i_tcon_of_table[] = {
  1299. { .compatible = "allwinner,sun4i-a10-tcon", .data = &sun4i_a10_quirks },
  1300. { .compatible = "allwinner,sun5i-a13-tcon", .data = &sun5i_a13_quirks },
  1301. { .compatible = "allwinner,sun6i-a31-tcon", .data = &sun6i_a31_quirks },
  1302. { .compatible = "allwinner,sun6i-a31s-tcon", .data = &sun6i_a31s_quirks },
  1303. { .compatible = "allwinner,sun7i-a20-tcon", .data = &sun7i_a20_quirks },
  1304. { .compatible = "allwinner,sun7i-a20-tcon0", .data = &sun7i_a20_tcon0_quirks },
  1305. { .compatible = "allwinner,sun7i-a20-tcon1", .data = &sun7i_a20_quirks },
  1306. { .compatible = "allwinner,sun8i-a23-tcon", .data = &sun8i_a33_quirks },
  1307. { .compatible = "allwinner,sun8i-a33-tcon", .data = &sun8i_a33_quirks },
  1308. { .compatible = "allwinner,sun8i-a83t-tcon-lcd", .data = &sun8i_a83t_lcd_quirks },
  1309. { .compatible = "allwinner,sun8i-a83t-tcon-tv", .data = &sun8i_a83t_tv_quirks },
  1310. { .compatible = "allwinner,sun8i-r40-tcon-tv", .data = &sun8i_r40_tv_quirks },
  1311. { .compatible = "allwinner,sun8i-v3s-tcon", .data = &sun8i_v3s_quirks },
  1312. { .compatible = "allwinner,sun9i-a80-tcon-lcd", .data = &sun9i_a80_tcon_lcd_quirks },
  1313. { .compatible = "allwinner,sun9i-a80-tcon-tv", .data = &sun9i_a80_tcon_tv_quirks },
  1314. { .compatible = "allwinner,sun20i-d1-tcon-lcd", .data = &sun20i_d1_lcd_quirks },
  1315. { .compatible = "allwinner,sun20i-d1-tcon-tv", .data = &sun8i_r40_tv_quirks },
  1316. { }
  1317. };
  1318. MODULE_DEVICE_TABLE(of, sun4i_tcon_of_table);
  1319. EXPORT_SYMBOL(sun4i_tcon_of_table);
  1320. static struct platform_driver sun4i_tcon_platform_driver = {
  1321. .probe = sun4i_tcon_probe,
  1322. .remove_new = sun4i_tcon_remove,
  1323. .driver = {
  1324. .name = "sun4i-tcon",
  1325. .of_match_table = sun4i_tcon_of_table,
  1326. },
  1327. };
  1328. module_platform_driver(sun4i_tcon_platform_driver);
  1329. MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
  1330. MODULE_DESCRIPTION("Allwinner A10 Timing Controller Driver");
  1331. MODULE_LICENSE("GPL");