PageRenderTime 1530ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 0ms

/drivers/staging/gma500/mdfld_pyr_cmd.c

https://github.com/Mengqi/linux-2.6
C | 558 lines | 388 code | 93 blank | 77 comment | 56 complexity | e73bceb3cfaf640105ae21f71dc8f17e MD5 | raw file
  1. /*
  2. * Copyright (c) 2010 Intel Corporation
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a
  5. * copy of this software and associated documentation files (the "Software"),
  6. * to deal in the Software without restriction, including without limitation
  7. * the rights to use, copy, modify, merge, publish, distribute, sublicensen
  8. * and/or sell copies of the Software, and to permit persons to whom the
  9. * Software is furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice (including the next
  12. * paragraph) shall be included in all copies or substantial portions of the
  13. * Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  18. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  21. * DEALINGS IN THE SOFTWARE.
  22. *
  23. * Authors:
  24. * Thomas Eaton <thomas.g.eaton@intel.com>
  25. * Scott Rowe <scott.m.rowe@intel.com>
  26. */
  27. #include "mdfld_dsi_dbi.h"
  28. #include "mdfld_dsi_dpi.h"
  29. #include "mdfld_dsi_output.h"
  30. #include "mdfld_output.h"
  31. #include "mdfld_dsi_dbi_dpu.h"
  32. #include "mdfld_dsi_pkg_sender.h"
  33. #include "displays/pyr_cmd.h"
  34. static struct drm_display_mode *pyr_cmd_get_config_mode(struct drm_device *dev)
  35. {
  36. struct drm_display_mode *mode;
  37. mode = kzalloc(sizeof(*mode), GFP_KERNEL);
  38. if (!mode) {
  39. dev_err(dev->dev, "Out of memory\n");
  40. return NULL;
  41. }
  42. dev_dbg(dev->dev, "hdisplay is %d\n", mode->hdisplay);
  43. dev_dbg(dev->dev, "vdisplay is %d\n", mode->vdisplay);
  44. dev_dbg(dev->dev, "HSS is %d\n", mode->hsync_start);
  45. dev_dbg(dev->dev, "HSE is %d\n", mode->hsync_end);
  46. dev_dbg(dev->dev, "htotal is %d\n", mode->htotal);
  47. dev_dbg(dev->dev, "VSS is %d\n", mode->vsync_start);
  48. dev_dbg(dev->dev, "VSE is %d\n", mode->vsync_end);
  49. dev_dbg(dev->dev, "vtotal is %d\n", mode->vtotal);
  50. dev_dbg(dev->dev, "clock is %d\n", mode->clock);
  51. mode->hdisplay = 480;
  52. mode->vdisplay = 864;
  53. mode->hsync_start = 487;
  54. mode->hsync_end = 490;
  55. mode->htotal = 499;
  56. mode->vsync_start = 874;
  57. mode->vsync_end = 878;
  58. mode->vtotal = 886;
  59. mode->clock = 25777;
  60. drm_mode_set_name(mode);
  61. drm_mode_set_crtcinfo(mode, 0);
  62. mode->type |= DRM_MODE_TYPE_PREFERRED;
  63. return mode;
  64. }
  65. static bool pyr_dsi_dbi_mode_fixup(struct drm_encoder *encoder,
  66. struct drm_display_mode *mode,
  67. struct drm_display_mode *adjusted_mode)
  68. {
  69. struct drm_device *dev = encoder->dev;
  70. struct drm_display_mode *fixed_mode = pyr_cmd_get_config_mode(dev);
  71. if (fixed_mode) {
  72. adjusted_mode->hdisplay = fixed_mode->hdisplay;
  73. adjusted_mode->hsync_start = fixed_mode->hsync_start;
  74. adjusted_mode->hsync_end = fixed_mode->hsync_end;
  75. adjusted_mode->htotal = fixed_mode->htotal;
  76. adjusted_mode->vdisplay = fixed_mode->vdisplay;
  77. adjusted_mode->vsync_start = fixed_mode->vsync_start;
  78. adjusted_mode->vsync_end = fixed_mode->vsync_end;
  79. adjusted_mode->vtotal = fixed_mode->vtotal;
  80. adjusted_mode->clock = fixed_mode->clock;
  81. drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
  82. kfree(fixed_mode);
  83. }
  84. return true;
  85. }
  86. static void pyr_dsi_dbi_set_power(struct drm_encoder *encoder, bool on)
  87. {
  88. int ret = 0;
  89. struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
  90. struct mdfld_dsi_dbi_output *dbi_output =
  91. MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
  92. struct drm_device *dev = encoder->dev;
  93. struct drm_psb_private *dev_priv = dev->dev_private;
  94. u32 reg_offset = 0;
  95. int pipe = (dbi_output->channel_num == 0) ? 0 : 2;
  96. dev_dbg(dev->dev, "pipe %d : %s, panel on: %s\n", pipe,
  97. on ? "On" : "Off",
  98. dbi_output->dbi_panel_on ? "True" : "False");
  99. if (pipe == 2) {
  100. if (on)
  101. dev_priv->dual_mipi = true;
  102. else
  103. dev_priv->dual_mipi = false;
  104. reg_offset = MIPIC_REG_OFFSET;
  105. } else {
  106. if (!on)
  107. dev_priv->dual_mipi = false;
  108. }
  109. if (!gma_power_begin(dev, true)) {
  110. dev_err(dev->dev, "hw begin failed\n");
  111. return;
  112. }
  113. if (on) {
  114. if (dbi_output->dbi_panel_on)
  115. goto out_err;
  116. ret = mdfld_dsi_dbi_update_power(dbi_output, DRM_MODE_DPMS_ON);
  117. if (ret) {
  118. dev_err(dev->dev, "power on error\n");
  119. goto out_err;
  120. }
  121. dbi_output->dbi_panel_on = true;
  122. if (pipe == 2) {
  123. dev_priv->dbi_panel_on2 = true;
  124. } else {
  125. dev_priv->dbi_panel_on = true;
  126. mdfld_enable_te(dev, 0);
  127. }
  128. } else {
  129. if (!dbi_output->dbi_panel_on && !dbi_output->first_boot)
  130. goto out_err;
  131. dbi_output->dbi_panel_on = false;
  132. dbi_output->first_boot = false;
  133. if (pipe == 2) {
  134. dev_priv->dbi_panel_on2 = false;
  135. mdfld_disable_te(dev, 2);
  136. } else {
  137. dev_priv->dbi_panel_on = false;
  138. mdfld_disable_te(dev, 0);
  139. if (dev_priv->dbi_panel_on2)
  140. mdfld_enable_te(dev, 2);
  141. }
  142. ret = mdfld_dsi_dbi_update_power(dbi_output, DRM_MODE_DPMS_OFF);
  143. if (ret) {
  144. dev_err(dev->dev, "power on error\n");
  145. goto out_err;
  146. }
  147. }
  148. out_err:
  149. gma_power_end(dev);
  150. if (ret)
  151. dev_err(dev->dev, "failed\n");
  152. }
  153. static void pyr_dsi_controller_dbi_init(struct mdfld_dsi_config *dsi_config,
  154. int pipe)
  155. {
  156. struct drm_device *dev = dsi_config->dev;
  157. u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0;
  158. int lane_count = dsi_config->lane_count;
  159. u32 val = 0;
  160. dev_dbg(dev->dev, "Init DBI interface on pipe %d...\n", pipe);
  161. /* Un-ready device */
  162. REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000000);
  163. /* Init dsi adapter before kicking off */
  164. REG_WRITE((MIPIA_CONTROL_REG + reg_offset), 0x00000018);
  165. /* TODO: figure out how to setup these registers */
  166. REG_WRITE((MIPIA_DPHY_PARAM_REG + reg_offset), 0x150c600F);
  167. REG_WRITE((MIPIA_CLK_LANE_SWITCH_TIME_CNT_REG + reg_offset),
  168. 0x000a0014);
  169. REG_WRITE((MIPIA_DBI_BW_CTRL_REG + reg_offset), 0x00000400);
  170. REG_WRITE((MIPIA_HS_LS_DBI_ENABLE_REG + reg_offset), 0x00000000);
  171. /* Enable all interrupts */
  172. REG_WRITE((MIPIA_INTR_EN_REG + reg_offset), 0xffffffff);
  173. /* Max value: 20 clock cycles of txclkesc */
  174. REG_WRITE((MIPIA_TURN_AROUND_TIMEOUT_REG + reg_offset), 0x0000001f);
  175. /* Min 21 txclkesc, max: ffffh */
  176. REG_WRITE((MIPIA_DEVICE_RESET_TIMER_REG + reg_offset), 0x0000ffff);
  177. /* Min: 7d0 max: 4e20 */
  178. REG_WRITE((MIPIA_INIT_COUNT_REG + reg_offset), 0x00000fa0);
  179. /* Set up func_prg */
  180. val |= lane_count;
  181. val |= (dsi_config->channel_num << DSI_DBI_VIRT_CHANNEL_OFFSET);
  182. val |= DSI_DBI_COLOR_FORMAT_OPTION2;
  183. REG_WRITE((MIPIA_DSI_FUNC_PRG_REG + reg_offset), val);
  184. REG_WRITE((MIPIA_HS_TX_TIMEOUT_REG + reg_offset), 0x3fffff);
  185. REG_WRITE((MIPIA_LP_RX_TIMEOUT_REG + reg_offset), 0xffff);
  186. /* De-assert dbi_stall when half of DBI FIFO is empty */
  187. /* REG_WRITE((MIPIA_DBI_FIFO_THROTTLE_REG + reg_offset), 0x00000000); */
  188. REG_WRITE((MIPIA_HIGH_LOW_SWITCH_COUNT_REG + reg_offset), 0x46);
  189. REG_WRITE((MIPIA_EOT_DISABLE_REG + reg_offset), 0x00000002);
  190. REG_WRITE((MIPIA_LP_BYTECLK_REG + reg_offset), 0x00000004);
  191. REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000001);
  192. }
  193. static void pyr_dsi_dbi_mode_set(struct drm_encoder *encoder,
  194. struct drm_display_mode *mode,
  195. struct drm_display_mode *adjusted_mode)
  196. {
  197. int ret = 0;
  198. struct drm_device *dev = encoder->dev;
  199. struct drm_psb_private *dev_priv = dev->dev_private;
  200. struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
  201. struct mdfld_dsi_dbi_output *dsi_output =
  202. MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
  203. struct mdfld_dsi_config *dsi_config =
  204. mdfld_dsi_encoder_get_config(dsi_encoder);
  205. struct mdfld_dsi_connector *dsi_connector = dsi_config->connector;
  206. int pipe = dsi_connector->pipe;
  207. u8 param = 0;
  208. /* Regs */
  209. u32 mipi_reg = MIPI;
  210. u32 dspcntr_reg = DSPACNTR;
  211. u32 pipeconf_reg = PIPEACONF;
  212. u32 reg_offset = 0;
  213. /* Values */
  214. u32 dspcntr_val = dev_priv->dspcntr;
  215. u32 pipeconf_val = dev_priv->pipeconf;
  216. u32 h_active_area = mode->hdisplay;
  217. u32 v_active_area = mode->vdisplay;
  218. u32 mipi_val = (PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX |
  219. TE_TRIGGER_GPIO_PIN);
  220. dev_dbg(dev->dev, "mipi_val =0x%x\n", mipi_val);
  221. dev_dbg(dev->dev, "type %s\n", (pipe == 2) ? "MIPI2" : "MIPI");
  222. dev_dbg(dev->dev, "h %d v %d\n", mode->hdisplay, mode->vdisplay);
  223. if (pipe == 2) {
  224. mipi_reg = MIPI_C;
  225. dspcntr_reg = DSPCCNTR;
  226. pipeconf_reg = PIPECCONF;
  227. reg_offset = MIPIC_REG_OFFSET;
  228. dspcntr_val = dev_priv->dspcntr2;
  229. pipeconf_val = dev_priv->pipeconf2;
  230. } else {
  231. mipi_val |= 0x2; /* Two lanes for port A and C respectively */
  232. }
  233. if (!gma_power_begin(dev, true)) {
  234. dev_err(dev->dev, "hw begin failed\n");
  235. return;
  236. }
  237. /* Set up pipe related registers */
  238. REG_WRITE(mipi_reg, mipi_val);
  239. REG_READ(mipi_reg);
  240. pyr_dsi_controller_dbi_init(dsi_config, pipe);
  241. msleep(20);
  242. REG_WRITE(dspcntr_reg, dspcntr_val);
  243. REG_READ(dspcntr_reg);
  244. /* 20ms delay before sending exit_sleep_mode */
  245. msleep(20);
  246. /* Send exit_sleep_mode DCS */
  247. ret = mdfld_dsi_dbi_send_dcs(dsi_output, exit_sleep_mode, NULL,
  248. 0, CMD_DATA_SRC_SYSTEM_MEM);
  249. if (ret) {
  250. dev_err(dev->dev, "sent exit_sleep_mode faild\n");
  251. goto out_err;
  252. }
  253. /*send set_tear_on DCS*/
  254. ret = mdfld_dsi_dbi_send_dcs(dsi_output, set_tear_on,
  255. &param, 1, CMD_DATA_SRC_SYSTEM_MEM);
  256. if (ret) {
  257. dev_err(dev->dev, "%s - sent set_tear_on faild\n", __func__);
  258. goto out_err;
  259. }
  260. /* Do some init stuff */
  261. mdfld_dsi_brightness_init(dsi_config, pipe);
  262. mdfld_dsi_gen_fifo_ready(dev, (MIPIA_GEN_FIFO_STAT_REG + reg_offset),
  263. HS_CTRL_FIFO_EMPTY | HS_DATA_FIFO_EMPTY);
  264. REG_WRITE(pipeconf_reg, pipeconf_val | PIPEACONF_DSR);
  265. REG_READ(pipeconf_reg);
  266. /* TODO: this looks ugly, try to move it to CRTC mode setting */
  267. if (pipe == 2)
  268. dev_priv->pipeconf2 |= PIPEACONF_DSR;
  269. else
  270. dev_priv->pipeconf |= PIPEACONF_DSR;
  271. dev_dbg(dev->dev, "pipeconf %x\n", REG_READ(pipeconf_reg));
  272. ret = mdfld_dsi_dbi_update_area(dsi_output, 0, 0,
  273. h_active_area - 1, v_active_area - 1);
  274. if (ret) {
  275. dev_err(dev->dev, "update area failed\n");
  276. goto out_err;
  277. }
  278. out_err:
  279. gma_power_end(dev);
  280. if (ret)
  281. dev_err(dev->dev, "mode set failed\n");
  282. else
  283. dev_dbg(dev->dev, "mode set done successfully\n");
  284. }
  285. static void pyr_dsi_dbi_prepare(struct drm_encoder *encoder)
  286. {
  287. struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
  288. struct mdfld_dsi_dbi_output *dbi_output =
  289. MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
  290. dbi_output->mode_flags |= MODE_SETTING_IN_ENCODER;
  291. dbi_output->mode_flags &= ~MODE_SETTING_ENCODER_DONE;
  292. pyr_dsi_dbi_set_power(encoder, false);
  293. }
  294. static void pyr_dsi_dbi_commit(struct drm_encoder *encoder)
  295. {
  296. struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
  297. struct mdfld_dsi_dbi_output *dbi_output =
  298. MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
  299. struct drm_device *dev = dbi_output->dev;
  300. struct drm_psb_private *dev_priv = dev->dev_private;
  301. struct psb_drm_dpu_rect rect;
  302. pyr_dsi_dbi_set_power(encoder, true);
  303. dbi_output->mode_flags &= ~MODE_SETTING_IN_ENCODER;
  304. rect.x = rect.y = 0;
  305. rect.width = 864;
  306. rect.height = 480;
  307. if (dbi_output->channel_num == 1) {
  308. dev_priv->dsr_fb_update |= MDFLD_DSR_2D_3D_2;
  309. /* If DPU enabled report a fullscreen damage */
  310. mdfld_dbi_dpu_report_damage(dev, MDFLD_PLANEC, &rect);
  311. } else {
  312. dev_priv->dsr_fb_update |= MDFLD_DSR_2D_3D_0;
  313. mdfld_dbi_dpu_report_damage(dev, MDFLD_PLANEA, &rect);
  314. }
  315. dbi_output->mode_flags |= MODE_SETTING_ENCODER_DONE;
  316. }
  317. static void pyr_dsi_dbi_dpms(struct drm_encoder *encoder, int mode)
  318. {
  319. struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
  320. struct mdfld_dsi_dbi_output *dbi_output =
  321. MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
  322. struct drm_device *dev = dbi_output->dev;
  323. dev_dbg(dev->dev, "%s\n", (mode == DRM_MODE_DPMS_ON ? "on" : "off"));
  324. if (mode == DRM_MODE_DPMS_ON)
  325. pyr_dsi_dbi_set_power(encoder, true);
  326. else
  327. pyr_dsi_dbi_set_power(encoder, false);
  328. }
  329. /*
  330. * Update the DBI MIPI Panel Frame Buffer.
  331. */
  332. static void pyr_dsi_dbi_update_fb(struct mdfld_dsi_dbi_output *dbi_output,
  333. int pipe)
  334. {
  335. struct mdfld_dsi_pkg_sender *sender =
  336. mdfld_dsi_encoder_get_pkg_sender(&dbi_output->base);
  337. struct drm_device *dev = dbi_output->dev;
  338. struct drm_crtc *crtc = dbi_output->base.base.crtc;
  339. struct psb_intel_crtc *psb_crtc = (crtc) ?
  340. to_psb_intel_crtc(crtc) : NULL;
  341. u32 dpll_reg = MRST_DPLL_A;
  342. u32 dspcntr_reg = DSPACNTR;
  343. u32 pipeconf_reg = PIPEACONF;
  344. u32 dsplinoff_reg = DSPALINOFF;
  345. u32 dspsurf_reg = DSPASURF;
  346. u32 hs_gen_ctrl_reg = HS_GEN_CTRL_REG;
  347. u32 gen_fifo_stat_reg = GEN_FIFO_STAT_REG;
  348. u32 reg_offset = 0;
  349. u32 intr_status;
  350. u32 fifo_stat_reg_val;
  351. u32 dpll_reg_val;
  352. u32 dspcntr_reg_val;
  353. u32 pipeconf_reg_val;
  354. /* If mode setting on-going, back off */
  355. if ((dbi_output->mode_flags & MODE_SETTING_ON_GOING) ||
  356. (psb_crtc && psb_crtc->mode_flags & MODE_SETTING_ON_GOING) ||
  357. !(dbi_output->mode_flags & MODE_SETTING_ENCODER_DONE))
  358. return;
  359. /*
  360. * Look for errors here. In particular we're checking for whatever
  361. * error status might have appeared during the last frame transmit
  362. * (memory write).
  363. *
  364. * Normally, the bits we're testing here would be set infrequently,
  365. * if at all. However, one panel (at least) returns at least one
  366. * error bit on most frames. So we've disabled the kernel message
  367. * for now.
  368. *
  369. * Still clear whatever error bits are set, except don't clear the
  370. * ones that would make the Penwell DSI controller reset if we
  371. * cleared them.
  372. */
  373. intr_status = REG_READ(INTR_STAT_REG);
  374. if ((intr_status & 0x26FFFFFF) != 0) {
  375. /* dev_err(dev->dev, "DSI status: 0x%08X\n", intr_status); */
  376. intr_status &= 0x26F3FFFF;
  377. REG_WRITE(INTR_STAT_REG, intr_status);
  378. }
  379. if (pipe == 2) {
  380. dspcntr_reg = DSPCCNTR;
  381. pipeconf_reg = PIPECCONF;
  382. dsplinoff_reg = DSPCLINOFF;
  383. dspsurf_reg = DSPCSURF;
  384. hs_gen_ctrl_reg = HS_GEN_CTRL_REG + MIPIC_REG_OFFSET;
  385. gen_fifo_stat_reg = GEN_FIFO_STAT_REG + MIPIC_REG_OFFSET,
  386. reg_offset = MIPIC_REG_OFFSET;
  387. }
  388. if (!gma_power_begin(dev, true)) {
  389. dev_err(dev->dev, "hw begin failed\n");
  390. return;
  391. }
  392. fifo_stat_reg_val = REG_READ(MIPIA_GEN_FIFO_STAT_REG + reg_offset);
  393. dpll_reg_val = REG_READ(dpll_reg);
  394. dspcntr_reg_val = REG_READ(dspcntr_reg);
  395. pipeconf_reg_val = REG_READ(pipeconf_reg);
  396. if (!(fifo_stat_reg_val & (1 << 27)) ||
  397. (dpll_reg_val & DPLL_VCO_ENABLE) ||
  398. !(dspcntr_reg_val & DISPLAY_PLANE_ENABLE) ||
  399. !(pipeconf_reg_val & DISPLAY_PLANE_ENABLE)) {
  400. goto update_fb_out0;
  401. }
  402. /* Refresh plane changes */
  403. REG_WRITE(dsplinoff_reg, REG_READ(dsplinoff_reg));
  404. REG_WRITE(dspsurf_reg, REG_READ(dspsurf_reg));
  405. REG_READ(dspsurf_reg);
  406. mdfld_dsi_send_dcs(sender,
  407. write_mem_start,
  408. NULL,
  409. 0,
  410. CMD_DATA_SRC_PIPE,
  411. MDFLD_DSI_SEND_PACKAGE);
  412. /*
  413. * The idea here is to transmit a Generic Read command after the
  414. * Write Memory Start/Continue commands finish. This asks for
  415. * the panel to return an "ACK No Errors," or (if it has errors
  416. * to report) an Error Report. This allows us to monitor the
  417. * panel's perception of the health of the DSI.
  418. */
  419. mdfld_dsi_gen_fifo_ready(dev, gen_fifo_stat_reg,
  420. HS_CTRL_FIFO_EMPTY | HS_DATA_FIFO_EMPTY);
  421. REG_WRITE(hs_gen_ctrl_reg, (1 << WORD_COUNTS_POS) | GEN_READ_0);
  422. dbi_output->dsr_fb_update_done = true;
  423. update_fb_out0:
  424. gma_power_end(dev);
  425. }
  426. /*
  427. * TODO: will be removed later, should work out display interfaces for power
  428. */
  429. void pyr_dsi_adapter_init(struct mdfld_dsi_config *dsi_config, int pipe)
  430. {
  431. if (!dsi_config || (pipe != 0 && pipe != 2)) {
  432. WARN_ON(1);
  433. return;
  434. }
  435. pyr_dsi_controller_dbi_init(dsi_config, pipe);
  436. }
  437. static int pyr_cmd_get_panel_info(struct drm_device *dev, int pipe,
  438. struct panel_info *pi)
  439. {
  440. if (!dev || !pi)
  441. return -EINVAL;
  442. pi->width_mm = PYR_PANEL_WIDTH;
  443. pi->height_mm = PYR_PANEL_HEIGHT;
  444. return 0;
  445. }
  446. /* PYR DBI encoder helper funcs */
  447. static const struct drm_encoder_helper_funcs pyr_dsi_dbi_helper_funcs = {
  448. .dpms = pyr_dsi_dbi_dpms,
  449. .mode_fixup = pyr_dsi_dbi_mode_fixup,
  450. .prepare = pyr_dsi_dbi_prepare,
  451. .mode_set = pyr_dsi_dbi_mode_set,
  452. .commit = pyr_dsi_dbi_commit,
  453. };
  454. /* PYR DBI encoder funcs */
  455. static const struct drm_encoder_funcs mdfld_dsi_dbi_encoder_funcs = {
  456. .destroy = drm_encoder_cleanup,
  457. };
  458. void pyr_cmd_init(struct drm_device *dev, struct panel_funcs *p_funcs)
  459. {
  460. p_funcs->encoder_funcs = &mdfld_dsi_dbi_encoder_funcs;
  461. p_funcs->encoder_helper_funcs = &pyr_dsi_dbi_helper_funcs;
  462. p_funcs->get_config_mode = &pyr_cmd_get_config_mode;
  463. p_funcs->update_fb = pyr_dsi_dbi_update_fb;
  464. p_funcs->get_panel_info = pyr_cmd_get_panel_info;
  465. }