1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Copyright (C) 2012 Texas Instruments |
4 | * Author: Rob Clark <robdclark@gmail.com> |
5 | */ |
6 | |
7 | #include <linux/delay.h> |
8 | #include <linux/dma-mapping.h> |
9 | #include <linux/of_graph.h> |
10 | #include <linux/pm_runtime.h> |
11 | |
12 | #include <drm/drm_atomic.h> |
13 | #include <drm/drm_atomic_helper.h> |
14 | #include <drm/drm_crtc.h> |
15 | #include <drm/drm_fb_dma_helper.h> |
16 | #include <drm/drm_fourcc.h> |
17 | #include <drm/drm_framebuffer.h> |
18 | #include <drm/drm_gem_dma_helper.h> |
19 | #include <drm/drm_modeset_helper_vtables.h> |
20 | #include <drm/drm_print.h> |
21 | #include <drm/drm_vblank.h> |
22 | |
23 | #include "tilcdc_drv.h" |
24 | #include "tilcdc_regs.h" |
25 | |
26 | #define TILCDC_VBLANK_SAFETY_THRESHOLD_US 1000 |
27 | #define TILCDC_PALETTE_SIZE 32 |
28 | #define TILCDC_PALETTE_FIRST_ENTRY 0x4000 |
29 | |
30 | struct tilcdc_crtc { |
31 | struct drm_crtc base; |
32 | |
33 | struct drm_plane primary; |
34 | const struct tilcdc_panel_info *info; |
35 | struct drm_pending_vblank_event *event; |
36 | struct mutex enable_lock; |
37 | bool enabled; |
38 | bool shutdown; |
39 | wait_queue_head_t frame_done_wq; |
40 | bool frame_done; |
41 | spinlock_t irq_lock; |
42 | |
43 | unsigned int lcd_fck_rate; |
44 | |
45 | ktime_t last_vblank; |
46 | unsigned int hvtotal_us; |
47 | |
48 | struct drm_framebuffer *next_fb; |
49 | |
50 | /* Only set if an external encoder is connected */ |
51 | bool simulate_vesa_sync; |
52 | |
53 | int sync_lost_count; |
54 | bool frame_intact; |
55 | struct work_struct recover_work; |
56 | |
57 | dma_addr_t palette_dma_handle; |
58 | u16 *palette_base; |
59 | struct completion palette_loaded; |
60 | }; |
61 | #define to_tilcdc_crtc(x) container_of(x, struct tilcdc_crtc, base) |
62 | |
63 | static void set_scanout(struct drm_crtc *crtc, struct drm_framebuffer *fb) |
64 | { |
65 | struct drm_device *dev = crtc->dev; |
66 | struct tilcdc_drm_private *priv = dev->dev_private; |
67 | struct drm_gem_dma_object *gem; |
68 | dma_addr_t start, end; |
69 | u64 dma_base_and_ceiling; |
70 | |
71 | gem = drm_fb_dma_get_gem_obj(fb, plane: 0); |
72 | |
73 | start = gem->dma_addr + fb->offsets[0] + |
74 | crtc->y * fb->pitches[0] + |
75 | crtc->x * fb->format->cpp[0]; |
76 | |
77 | end = start + (crtc->mode.vdisplay * fb->pitches[0]); |
78 | |
79 | /* Write LCDC_DMA_FB_BASE_ADDR_0_REG and LCDC_DMA_FB_CEILING_ADDR_0_REG |
80 | * with a single insruction, if available. This should make it more |
81 | * unlikely that LCDC would fetch the DMA addresses in the middle of |
82 | * an update. |
83 | */ |
84 | if (priv->rev == 1) |
85 | end -= 1; |
86 | |
87 | dma_base_and_ceiling = (u64)end << 32 | start; |
88 | tilcdc_write64(dev, LCDC_DMA_FB_BASE_ADDR_0_REG, data: dma_base_and_ceiling); |
89 | } |
90 | |
91 | /* |
92 | * The driver currently only supports only true color formats. For |
93 | * true color the palette block is bypassed, but a 32 byte palette |
94 | * should still be loaded. The first 16-bit entry must be 0x4000 while |
95 | * all other entries must be zeroed. |
96 | */ |
97 | static void tilcdc_crtc_load_palette(struct drm_crtc *crtc) |
98 | { |
99 | struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); |
100 | struct drm_device *dev = crtc->dev; |
101 | struct tilcdc_drm_private *priv = dev->dev_private; |
102 | int ret; |
103 | |
104 | reinit_completion(x: &tilcdc_crtc->palette_loaded); |
105 | |
106 | /* Tell the LCDC where the palette is located. */ |
107 | tilcdc_write(dev, LCDC_DMA_FB_BASE_ADDR_0_REG, |
108 | data: tilcdc_crtc->palette_dma_handle); |
109 | tilcdc_write(dev, LCDC_DMA_FB_CEILING_ADDR_0_REG, |
110 | data: (u32) tilcdc_crtc->palette_dma_handle + |
111 | TILCDC_PALETTE_SIZE - 1); |
112 | |
113 | /* Set dma load mode for palette loading only. */ |
114 | tilcdc_write_mask(dev, LCDC_RASTER_CTRL_REG, |
115 | LCDC_PALETTE_LOAD_MODE(PALETTE_ONLY), |
116 | LCDC_PALETTE_LOAD_MODE_MASK); |
117 | |
118 | /* Enable DMA Palette Loaded Interrupt */ |
119 | if (priv->rev == 1) |
120 | tilcdc_set(dev, LCDC_RASTER_CTRL_REG, LCDC_V1_PL_INT_ENA); |
121 | else |
122 | tilcdc_write(dev, LCDC_INT_ENABLE_SET_REG, LCDC_V2_PL_INT_ENA); |
123 | |
124 | /* Enable LCDC DMA and wait for palette to be loaded. */ |
125 | tilcdc_clear_irqstatus(dev, mask: 0xffffffff); |
126 | tilcdc_set(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ENABLE); |
127 | |
128 | ret = wait_for_completion_timeout(x: &tilcdc_crtc->palette_loaded, |
129 | timeout: msecs_to_jiffies(m: 50)); |
130 | if (ret == 0) |
131 | dev_err(dev->dev, "%s: Palette loading timeout" , __func__); |
132 | |
133 | /* Disable LCDC DMA and DMA Palette Loaded Interrupt. */ |
134 | tilcdc_clear(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ENABLE); |
135 | if (priv->rev == 1) |
136 | tilcdc_clear(dev, LCDC_RASTER_CTRL_REG, LCDC_V1_PL_INT_ENA); |
137 | else |
138 | tilcdc_write(dev, LCDC_INT_ENABLE_CLR_REG, LCDC_V2_PL_INT_ENA); |
139 | } |
140 | |
141 | static void tilcdc_crtc_enable_irqs(struct drm_device *dev) |
142 | { |
143 | struct tilcdc_drm_private *priv = dev->dev_private; |
144 | |
145 | tilcdc_clear_irqstatus(dev, mask: 0xffffffff); |
146 | |
147 | if (priv->rev == 1) { |
148 | tilcdc_set(dev, LCDC_RASTER_CTRL_REG, |
149 | LCDC_V1_SYNC_LOST_INT_ENA | LCDC_V1_FRAME_DONE_INT_ENA | |
150 | LCDC_V1_UNDERFLOW_INT_ENA); |
151 | } else { |
152 | tilcdc_write(dev, LCDC_INT_ENABLE_SET_REG, |
153 | LCDC_V2_UNDERFLOW_INT_ENA | |
154 | LCDC_FRAME_DONE | LCDC_SYNC_LOST); |
155 | } |
156 | } |
157 | |
158 | static void tilcdc_crtc_disable_irqs(struct drm_device *dev) |
159 | { |
160 | struct tilcdc_drm_private *priv = dev->dev_private; |
161 | |
162 | /* disable irqs that we might have enabled: */ |
163 | if (priv->rev == 1) { |
164 | tilcdc_clear(dev, LCDC_RASTER_CTRL_REG, |
165 | LCDC_V1_SYNC_LOST_INT_ENA | LCDC_V1_FRAME_DONE_INT_ENA | |
166 | LCDC_V1_UNDERFLOW_INT_ENA | LCDC_V1_PL_INT_ENA); |
167 | tilcdc_clear(dev, LCDC_DMA_CTRL_REG, |
168 | LCDC_V1_END_OF_FRAME_INT_ENA); |
169 | } else { |
170 | tilcdc_write(dev, LCDC_INT_ENABLE_CLR_REG, |
171 | LCDC_V2_UNDERFLOW_INT_ENA | LCDC_V2_PL_INT_ENA | |
172 | LCDC_V2_END_OF_FRAME0_INT_ENA | |
173 | LCDC_FRAME_DONE | LCDC_SYNC_LOST); |
174 | } |
175 | } |
176 | |
177 | static void reset(struct drm_crtc *crtc) |
178 | { |
179 | struct drm_device *dev = crtc->dev; |
180 | struct tilcdc_drm_private *priv = dev->dev_private; |
181 | |
182 | if (priv->rev != 2) |
183 | return; |
184 | |
185 | tilcdc_set(dev, LCDC_CLK_RESET_REG, LCDC_CLK_MAIN_RESET); |
186 | usleep_range(min: 250, max: 1000); |
187 | tilcdc_clear(dev, LCDC_CLK_RESET_REG, LCDC_CLK_MAIN_RESET); |
188 | } |
189 | |
190 | /* |
191 | * Calculate the percentage difference between the requested pixel clock rate |
192 | * and the effective rate resulting from calculating the clock divider value. |
193 | */ |
194 | static unsigned int tilcdc_pclk_diff(unsigned long rate, |
195 | unsigned long real_rate) |
196 | { |
197 | int r = rate / 100, rr = real_rate / 100; |
198 | |
199 | return (unsigned int)(abs(((rr - r) * 100) / r)); |
200 | } |
201 | |
202 | static void tilcdc_crtc_set_clk(struct drm_crtc *crtc) |
203 | { |
204 | struct drm_device *dev = crtc->dev; |
205 | struct tilcdc_drm_private *priv = dev->dev_private; |
206 | struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); |
207 | unsigned long clk_rate, real_pclk_rate, pclk_rate; |
208 | unsigned int clkdiv; |
209 | int ret; |
210 | |
211 | clkdiv = 2; /* first try using a standard divider of 2 */ |
212 | |
213 | /* mode.clock is in KHz, set_rate wants parameter in Hz */ |
214 | pclk_rate = crtc->mode.clock * 1000; |
215 | |
216 | ret = clk_set_rate(clk: priv->clk, rate: pclk_rate * clkdiv); |
217 | clk_rate = clk_get_rate(clk: priv->clk); |
218 | real_pclk_rate = clk_rate / clkdiv; |
219 | if (ret < 0 || tilcdc_pclk_diff(rate: pclk_rate, real_rate: real_pclk_rate) > 5) { |
220 | /* |
221 | * If we fail to set the clock rate (some architectures don't |
222 | * use the common clock framework yet and may not implement |
223 | * all the clk API calls for every clock), try the next best |
224 | * thing: adjusting the clock divider, unless clk_get_rate() |
225 | * failed as well. |
226 | */ |
227 | if (!clk_rate) { |
228 | /* Nothing more we can do. Just bail out. */ |
229 | dev_err(dev->dev, |
230 | "failed to set the pixel clock - unable to read current lcdc clock rate\n" ); |
231 | return; |
232 | } |
233 | |
234 | clkdiv = DIV_ROUND_CLOSEST(clk_rate, pclk_rate); |
235 | |
236 | /* |
237 | * Emit a warning if the real clock rate resulting from the |
238 | * calculated divider differs much from the requested rate. |
239 | * |
240 | * 5% is an arbitrary value - LCDs are usually quite tolerant |
241 | * about pixel clock rates. |
242 | */ |
243 | real_pclk_rate = clk_rate / clkdiv; |
244 | |
245 | if (tilcdc_pclk_diff(rate: pclk_rate, real_rate: real_pclk_rate) > 5) { |
246 | dev_warn(dev->dev, |
247 | "effective pixel clock rate (%luHz) differs from the requested rate (%luHz)\n" , |
248 | real_pclk_rate, pclk_rate); |
249 | } |
250 | } |
251 | |
252 | tilcdc_crtc->lcd_fck_rate = clk_rate; |
253 | |
254 | DBG("lcd_clk=%u, mode clock=%d, div=%u" , |
255 | tilcdc_crtc->lcd_fck_rate, crtc->mode.clock, clkdiv); |
256 | |
257 | /* Configure the LCD clock divisor. */ |
258 | tilcdc_write(dev, LCDC_CTRL_REG, LCDC_CLK_DIVISOR(clkdiv) | |
259 | LCDC_RASTER_MODE); |
260 | |
261 | if (priv->rev == 2) |
262 | tilcdc_set(dev, LCDC_CLK_ENABLE_REG, |
263 | LCDC_V2_DMA_CLK_EN | LCDC_V2_LIDD_CLK_EN | |
264 | LCDC_V2_CORE_CLK_EN); |
265 | } |
266 | |
267 | static uint tilcdc_mode_hvtotal(const struct drm_display_mode *mode) |
268 | { |
269 | return (uint) div_u64(dividend: 1000llu * mode->htotal * mode->vtotal, |
270 | divisor: mode->clock); |
271 | } |
272 | |
273 | static void tilcdc_crtc_set_mode(struct drm_crtc *crtc) |
274 | { |
275 | struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); |
276 | struct drm_device *dev = crtc->dev; |
277 | struct tilcdc_drm_private *priv = dev->dev_private; |
278 | const struct tilcdc_panel_info *info = tilcdc_crtc->info; |
279 | uint32_t reg, hbp, hfp, hsw, vbp, vfp, vsw; |
280 | struct drm_display_mode *mode = &crtc->state->adjusted_mode; |
281 | struct drm_framebuffer *fb = crtc->primary->state->fb; |
282 | |
283 | if (WARN_ON(!info)) |
284 | return; |
285 | |
286 | if (WARN_ON(!fb)) |
287 | return; |
288 | |
289 | /* Configure the Burst Size and fifo threshold of DMA: */ |
290 | reg = tilcdc_read(dev, LCDC_DMA_CTRL_REG) & ~0x00000770; |
291 | switch (info->dma_burst_sz) { |
292 | case 1: |
293 | reg |= LCDC_DMA_BURST_SIZE(LCDC_DMA_BURST_1); |
294 | break; |
295 | case 2: |
296 | reg |= LCDC_DMA_BURST_SIZE(LCDC_DMA_BURST_2); |
297 | break; |
298 | case 4: |
299 | reg |= LCDC_DMA_BURST_SIZE(LCDC_DMA_BURST_4); |
300 | break; |
301 | case 8: |
302 | reg |= LCDC_DMA_BURST_SIZE(LCDC_DMA_BURST_8); |
303 | break; |
304 | case 16: |
305 | reg |= LCDC_DMA_BURST_SIZE(LCDC_DMA_BURST_16); |
306 | break; |
307 | default: |
308 | dev_err(dev->dev, "invalid burst size\n" ); |
309 | return; |
310 | } |
311 | reg |= (info->fifo_th << 8); |
312 | tilcdc_write(dev, LCDC_DMA_CTRL_REG, data: reg); |
313 | |
314 | /* Configure timings: */ |
315 | hbp = mode->htotal - mode->hsync_end; |
316 | hfp = mode->hsync_start - mode->hdisplay; |
317 | hsw = mode->hsync_end - mode->hsync_start; |
318 | vbp = mode->vtotal - mode->vsync_end; |
319 | vfp = mode->vsync_start - mode->vdisplay; |
320 | vsw = mode->vsync_end - mode->vsync_start; |
321 | |
322 | DBG("%dx%d, hbp=%u, hfp=%u, hsw=%u, vbp=%u, vfp=%u, vsw=%u" , |
323 | mode->hdisplay, mode->vdisplay, hbp, hfp, hsw, vbp, vfp, vsw); |
324 | |
325 | /* Set AC Bias Period and Number of Transitions per Interrupt: */ |
326 | reg = tilcdc_read(dev, LCDC_RASTER_TIMING_2_REG) & ~0x000fff00; |
327 | reg |= LCDC_AC_BIAS_FREQUENCY(info->ac_bias) | |
328 | LCDC_AC_BIAS_TRANSITIONS_PER_INT(info->ac_bias_intrpt); |
329 | |
330 | /* |
331 | * subtract one from hfp, hbp, hsw because the hardware uses |
332 | * a value of 0 as 1 |
333 | */ |
334 | if (priv->rev == 2) { |
335 | /* clear bits we're going to set */ |
336 | reg &= ~0x78000033; |
337 | reg |= ((hfp-1) & 0x300) >> 8; |
338 | reg |= ((hbp-1) & 0x300) >> 4; |
339 | reg |= ((hsw-1) & 0x3c0) << 21; |
340 | } |
341 | tilcdc_write(dev, LCDC_RASTER_TIMING_2_REG, data: reg); |
342 | |
343 | reg = (((mode->hdisplay >> 4) - 1) << 4) | |
344 | (((hbp-1) & 0xff) << 24) | |
345 | (((hfp-1) & 0xff) << 16) | |
346 | (((hsw-1) & 0x3f) << 10); |
347 | if (priv->rev == 2) |
348 | reg |= (((mode->hdisplay >> 4) - 1) & 0x40) >> 3; |
349 | tilcdc_write(dev, LCDC_RASTER_TIMING_0_REG, data: reg); |
350 | |
351 | reg = ((mode->vdisplay - 1) & 0x3ff) | |
352 | ((vbp & 0xff) << 24) | |
353 | ((vfp & 0xff) << 16) | |
354 | (((vsw-1) & 0x3f) << 10); |
355 | tilcdc_write(dev, LCDC_RASTER_TIMING_1_REG, data: reg); |
356 | |
357 | /* |
358 | * be sure to set Bit 10 for the V2 LCDC controller, |
359 | * otherwise limited to 1024 pixels width, stopping |
360 | * 1920x1080 being supported. |
361 | */ |
362 | if (priv->rev == 2) { |
363 | if ((mode->vdisplay - 1) & 0x400) { |
364 | tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, |
365 | LCDC_LPP_B10); |
366 | } else { |
367 | tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, |
368 | LCDC_LPP_B10); |
369 | } |
370 | } |
371 | |
372 | /* Configure display type: */ |
373 | reg = tilcdc_read(dev, LCDC_RASTER_CTRL_REG) & |
374 | ~(LCDC_TFT_MODE | LCDC_MONO_8BIT_MODE | LCDC_MONOCHROME_MODE | |
375 | LCDC_V2_TFT_24BPP_MODE | LCDC_V2_TFT_24BPP_UNPACK | |
376 | 0x000ff000 /* Palette Loading Delay bits */); |
377 | reg |= LCDC_TFT_MODE; /* no monochrome/passive support */ |
378 | if (info->tft_alt_mode) |
379 | reg |= LCDC_TFT_ALT_ENABLE; |
380 | if (priv->rev == 2) { |
381 | switch (fb->format->format) { |
382 | case DRM_FORMAT_BGR565: |
383 | case DRM_FORMAT_RGB565: |
384 | break; |
385 | case DRM_FORMAT_XBGR8888: |
386 | case DRM_FORMAT_XRGB8888: |
387 | reg |= LCDC_V2_TFT_24BPP_UNPACK; |
388 | fallthrough; |
389 | case DRM_FORMAT_BGR888: |
390 | case DRM_FORMAT_RGB888: |
391 | reg |= LCDC_V2_TFT_24BPP_MODE; |
392 | break; |
393 | default: |
394 | dev_err(dev->dev, "invalid pixel format\n" ); |
395 | return; |
396 | } |
397 | } |
398 | reg |= info->fdd << 12; |
399 | tilcdc_write(dev, LCDC_RASTER_CTRL_REG, data: reg); |
400 | |
401 | if (info->invert_pxl_clk) |
402 | tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_PIXEL_CLOCK); |
403 | else |
404 | tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_PIXEL_CLOCK); |
405 | |
406 | if (info->sync_ctrl) |
407 | tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, LCDC_SYNC_CTRL); |
408 | else |
409 | tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_SYNC_CTRL); |
410 | |
411 | if (info->sync_edge) |
412 | tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, LCDC_SYNC_EDGE); |
413 | else |
414 | tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_SYNC_EDGE); |
415 | |
416 | if (mode->flags & DRM_MODE_FLAG_NHSYNC) |
417 | tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_HSYNC); |
418 | else |
419 | tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_HSYNC); |
420 | |
421 | if (mode->flags & DRM_MODE_FLAG_NVSYNC) |
422 | tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_VSYNC); |
423 | else |
424 | tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_VSYNC); |
425 | |
426 | if (info->raster_order) |
427 | tilcdc_set(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ORDER); |
428 | else |
429 | tilcdc_clear(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ORDER); |
430 | |
431 | tilcdc_crtc_set_clk(crtc); |
432 | |
433 | tilcdc_crtc_load_palette(crtc); |
434 | |
435 | set_scanout(crtc, fb); |
436 | |
437 | drm_mode_copy(dst: &crtc->hwmode, src: &crtc->state->adjusted_mode); |
438 | |
439 | tilcdc_crtc->hvtotal_us = |
440 | tilcdc_mode_hvtotal(mode: &crtc->hwmode); |
441 | } |
442 | |
443 | static void tilcdc_crtc_enable(struct drm_crtc *crtc) |
444 | { |
445 | struct drm_device *dev = crtc->dev; |
446 | struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); |
447 | unsigned long flags; |
448 | |
449 | mutex_lock(&tilcdc_crtc->enable_lock); |
450 | if (tilcdc_crtc->enabled || tilcdc_crtc->shutdown) { |
451 | mutex_unlock(lock: &tilcdc_crtc->enable_lock); |
452 | return; |
453 | } |
454 | |
455 | pm_runtime_get_sync(dev: dev->dev); |
456 | |
457 | reset(crtc); |
458 | |
459 | tilcdc_crtc_set_mode(crtc); |
460 | |
461 | tilcdc_crtc_enable_irqs(dev); |
462 | |
463 | tilcdc_clear(dev, LCDC_DMA_CTRL_REG, LCDC_DUAL_FRAME_BUFFER_ENABLE); |
464 | tilcdc_write_mask(dev, LCDC_RASTER_CTRL_REG, |
465 | LCDC_PALETTE_LOAD_MODE(DATA_ONLY), |
466 | LCDC_PALETTE_LOAD_MODE_MASK); |
467 | |
468 | /* There is no real chance for a race here as the time stamp |
469 | * is taken before the raster DMA is started. The spin-lock is |
470 | * taken to have a memory barrier after taking the time-stamp |
471 | * and to avoid a context switch between taking the stamp and |
472 | * enabling the raster. |
473 | */ |
474 | spin_lock_irqsave(&tilcdc_crtc->irq_lock, flags); |
475 | tilcdc_crtc->last_vblank = ktime_get(); |
476 | tilcdc_set(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ENABLE); |
477 | spin_unlock_irqrestore(lock: &tilcdc_crtc->irq_lock, flags); |
478 | |
479 | drm_crtc_vblank_on(crtc); |
480 | |
481 | tilcdc_crtc->enabled = true; |
482 | mutex_unlock(lock: &tilcdc_crtc->enable_lock); |
483 | } |
484 | |
485 | static void tilcdc_crtc_atomic_enable(struct drm_crtc *crtc, |
486 | struct drm_atomic_state *state) |
487 | { |
488 | tilcdc_crtc_enable(crtc); |
489 | } |
490 | |
491 | static void tilcdc_crtc_off(struct drm_crtc *crtc, bool shutdown) |
492 | { |
493 | struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); |
494 | struct drm_device *dev = crtc->dev; |
495 | int ret; |
496 | |
497 | mutex_lock(&tilcdc_crtc->enable_lock); |
498 | if (shutdown) |
499 | tilcdc_crtc->shutdown = true; |
500 | if (!tilcdc_crtc->enabled) { |
501 | mutex_unlock(lock: &tilcdc_crtc->enable_lock); |
502 | return; |
503 | } |
504 | tilcdc_crtc->frame_done = false; |
505 | tilcdc_clear(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ENABLE); |
506 | |
507 | /* |
508 | * Wait for framedone irq which will still come before putting |
509 | * things to sleep.. |
510 | */ |
511 | ret = wait_event_timeout(tilcdc_crtc->frame_done_wq, |
512 | tilcdc_crtc->frame_done, |
513 | msecs_to_jiffies(500)); |
514 | if (ret == 0) |
515 | dev_err(dev->dev, "%s: timeout waiting for framedone\n" , |
516 | __func__); |
517 | |
518 | drm_crtc_vblank_off(crtc); |
519 | |
520 | spin_lock_irq(lock: &crtc->dev->event_lock); |
521 | |
522 | if (crtc->state->event) { |
523 | drm_crtc_send_vblank_event(crtc, e: crtc->state->event); |
524 | crtc->state->event = NULL; |
525 | } |
526 | |
527 | spin_unlock_irq(lock: &crtc->dev->event_lock); |
528 | |
529 | tilcdc_crtc_disable_irqs(dev); |
530 | |
531 | pm_runtime_put_sync(dev: dev->dev); |
532 | |
533 | tilcdc_crtc->enabled = false; |
534 | mutex_unlock(lock: &tilcdc_crtc->enable_lock); |
535 | } |
536 | |
537 | static void tilcdc_crtc_disable(struct drm_crtc *crtc) |
538 | { |
539 | tilcdc_crtc_off(crtc, shutdown: false); |
540 | } |
541 | |
542 | static void tilcdc_crtc_atomic_disable(struct drm_crtc *crtc, |
543 | struct drm_atomic_state *state) |
544 | { |
545 | tilcdc_crtc_disable(crtc); |
546 | } |
547 | |
548 | static void tilcdc_crtc_atomic_flush(struct drm_crtc *crtc, |
549 | struct drm_atomic_state *state) |
550 | { |
551 | if (!crtc->state->event) |
552 | return; |
553 | |
554 | spin_lock_irq(lock: &crtc->dev->event_lock); |
555 | drm_crtc_send_vblank_event(crtc, e: crtc->state->event); |
556 | crtc->state->event = NULL; |
557 | spin_unlock_irq(lock: &crtc->dev->event_lock); |
558 | } |
559 | |
560 | void tilcdc_crtc_shutdown(struct drm_crtc *crtc) |
561 | { |
562 | tilcdc_crtc_off(crtc, shutdown: true); |
563 | } |
564 | |
565 | static bool tilcdc_crtc_is_on(struct drm_crtc *crtc) |
566 | { |
567 | return crtc->state && crtc->state->enable && crtc->state->active; |
568 | } |
569 | |
570 | static void tilcdc_crtc_recover_work(struct work_struct *work) |
571 | { |
572 | struct tilcdc_crtc *tilcdc_crtc = |
573 | container_of(work, struct tilcdc_crtc, recover_work); |
574 | struct drm_crtc *crtc = &tilcdc_crtc->base; |
575 | |
576 | dev_info(crtc->dev->dev, "%s: Reset CRTC" , __func__); |
577 | |
578 | drm_modeset_lock(lock: &crtc->mutex, NULL); |
579 | |
580 | if (!tilcdc_crtc_is_on(crtc)) |
581 | goto out; |
582 | |
583 | tilcdc_crtc_disable(crtc); |
584 | tilcdc_crtc_enable(crtc); |
585 | out: |
586 | drm_modeset_unlock(lock: &crtc->mutex); |
587 | } |
588 | |
589 | static void tilcdc_crtc_destroy(struct drm_crtc *crtc) |
590 | { |
591 | struct tilcdc_drm_private *priv = crtc->dev->dev_private; |
592 | |
593 | tilcdc_crtc_shutdown(crtc); |
594 | |
595 | flush_workqueue(priv->wq); |
596 | |
597 | of_node_put(node: crtc->port); |
598 | drm_crtc_cleanup(crtc); |
599 | } |
600 | |
601 | int tilcdc_crtc_update_fb(struct drm_crtc *crtc, |
602 | struct drm_framebuffer *fb, |
603 | struct drm_pending_vblank_event *event) |
604 | { |
605 | struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); |
606 | struct drm_device *dev = crtc->dev; |
607 | |
608 | if (tilcdc_crtc->event) { |
609 | dev_err(dev->dev, "already pending page flip!\n" ); |
610 | return -EBUSY; |
611 | } |
612 | |
613 | tilcdc_crtc->event = event; |
614 | |
615 | mutex_lock(&tilcdc_crtc->enable_lock); |
616 | |
617 | if (tilcdc_crtc->enabled) { |
618 | unsigned long flags; |
619 | ktime_t next_vblank; |
620 | s64 tdiff; |
621 | |
622 | spin_lock_irqsave(&tilcdc_crtc->irq_lock, flags); |
623 | |
624 | next_vblank = ktime_add_us(kt: tilcdc_crtc->last_vblank, |
625 | usec: tilcdc_crtc->hvtotal_us); |
626 | tdiff = ktime_to_us(ktime_sub(next_vblank, ktime_get())); |
627 | |
628 | if (tdiff < TILCDC_VBLANK_SAFETY_THRESHOLD_US) |
629 | tilcdc_crtc->next_fb = fb; |
630 | else |
631 | set_scanout(crtc, fb); |
632 | |
633 | spin_unlock_irqrestore(lock: &tilcdc_crtc->irq_lock, flags); |
634 | } |
635 | |
636 | mutex_unlock(lock: &tilcdc_crtc->enable_lock); |
637 | |
638 | return 0; |
639 | } |
640 | |
641 | static bool tilcdc_crtc_mode_fixup(struct drm_crtc *crtc, |
642 | const struct drm_display_mode *mode, |
643 | struct drm_display_mode *adjusted_mode) |
644 | { |
645 | struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); |
646 | |
647 | if (!tilcdc_crtc->simulate_vesa_sync) |
648 | return true; |
649 | |
650 | /* |
651 | * tilcdc does not generate VESA-compliant sync but aligns |
652 | * VS on the second edge of HS instead of first edge. |
653 | * We use adjusted_mode, to fixup sync by aligning both rising |
654 | * edges and add HSKEW offset to fix the sync. |
655 | */ |
656 | adjusted_mode->hskew = mode->hsync_end - mode->hsync_start; |
657 | adjusted_mode->flags |= DRM_MODE_FLAG_HSKEW; |
658 | |
659 | if (mode->flags & DRM_MODE_FLAG_NHSYNC) { |
660 | adjusted_mode->flags |= DRM_MODE_FLAG_PHSYNC; |
661 | adjusted_mode->flags &= ~DRM_MODE_FLAG_NHSYNC; |
662 | } else { |
663 | adjusted_mode->flags |= DRM_MODE_FLAG_NHSYNC; |
664 | adjusted_mode->flags &= ~DRM_MODE_FLAG_PHSYNC; |
665 | } |
666 | |
667 | return true; |
668 | } |
669 | |
670 | static int tilcdc_crtc_atomic_check(struct drm_crtc *crtc, |
671 | struct drm_atomic_state *state) |
672 | { |
673 | struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, |
674 | crtc); |
675 | /* If we are not active we don't care */ |
676 | if (!crtc_state->active) |
677 | return 0; |
678 | |
679 | if (state->planes[0].ptr != crtc->primary || |
680 | state->planes[0].state == NULL || |
681 | state->planes[0].state->crtc != crtc) { |
682 | dev_dbg(crtc->dev->dev, "CRTC primary plane must be present" ); |
683 | return -EINVAL; |
684 | } |
685 | |
686 | return 0; |
687 | } |
688 | |
689 | static int tilcdc_crtc_enable_vblank(struct drm_crtc *crtc) |
690 | { |
691 | struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); |
692 | struct drm_device *dev = crtc->dev; |
693 | struct tilcdc_drm_private *priv = dev->dev_private; |
694 | unsigned long flags; |
695 | |
696 | spin_lock_irqsave(&tilcdc_crtc->irq_lock, flags); |
697 | |
698 | tilcdc_clear_irqstatus(dev, LCDC_END_OF_FRAME0); |
699 | |
700 | if (priv->rev == 1) |
701 | tilcdc_set(dev, LCDC_DMA_CTRL_REG, |
702 | LCDC_V1_END_OF_FRAME_INT_ENA); |
703 | else |
704 | tilcdc_set(dev, LCDC_INT_ENABLE_SET_REG, |
705 | LCDC_V2_END_OF_FRAME0_INT_ENA); |
706 | |
707 | spin_unlock_irqrestore(lock: &tilcdc_crtc->irq_lock, flags); |
708 | |
709 | return 0; |
710 | } |
711 | |
712 | static void tilcdc_crtc_disable_vblank(struct drm_crtc *crtc) |
713 | { |
714 | struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); |
715 | struct drm_device *dev = crtc->dev; |
716 | struct tilcdc_drm_private *priv = dev->dev_private; |
717 | unsigned long flags; |
718 | |
719 | spin_lock_irqsave(&tilcdc_crtc->irq_lock, flags); |
720 | |
721 | if (priv->rev == 1) |
722 | tilcdc_clear(dev, LCDC_DMA_CTRL_REG, |
723 | LCDC_V1_END_OF_FRAME_INT_ENA); |
724 | else |
725 | tilcdc_clear(dev, LCDC_INT_ENABLE_SET_REG, |
726 | LCDC_V2_END_OF_FRAME0_INT_ENA); |
727 | |
728 | spin_unlock_irqrestore(lock: &tilcdc_crtc->irq_lock, flags); |
729 | } |
730 | |
731 | static void tilcdc_crtc_reset(struct drm_crtc *crtc) |
732 | { |
733 | struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); |
734 | struct drm_device *dev = crtc->dev; |
735 | int ret; |
736 | |
737 | drm_atomic_helper_crtc_reset(crtc); |
738 | |
739 | /* Turn the raster off if it for some reason is on. */ |
740 | pm_runtime_get_sync(dev: dev->dev); |
741 | if (tilcdc_read(dev, LCDC_RASTER_CTRL_REG) & LCDC_RASTER_ENABLE) { |
742 | /* Enable DMA Frame Done Interrupt */ |
743 | tilcdc_write(dev, LCDC_INT_ENABLE_SET_REG, LCDC_FRAME_DONE); |
744 | tilcdc_clear_irqstatus(dev, mask: 0xffffffff); |
745 | |
746 | tilcdc_crtc->frame_done = false; |
747 | tilcdc_clear(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ENABLE); |
748 | |
749 | ret = wait_event_timeout(tilcdc_crtc->frame_done_wq, |
750 | tilcdc_crtc->frame_done, |
751 | msecs_to_jiffies(500)); |
752 | if (ret == 0) |
753 | dev_err(dev->dev, "%s: timeout waiting for framedone\n" , |
754 | __func__); |
755 | } |
756 | pm_runtime_put_sync(dev: dev->dev); |
757 | } |
758 | |
759 | static const struct drm_crtc_funcs tilcdc_crtc_funcs = { |
760 | .destroy = tilcdc_crtc_destroy, |
761 | .set_config = drm_atomic_helper_set_config, |
762 | .page_flip = drm_atomic_helper_page_flip, |
763 | .reset = tilcdc_crtc_reset, |
764 | .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, |
765 | .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, |
766 | .enable_vblank = tilcdc_crtc_enable_vblank, |
767 | .disable_vblank = tilcdc_crtc_disable_vblank, |
768 | }; |
769 | |
770 | static enum drm_mode_status |
771 | tilcdc_crtc_mode_valid(struct drm_crtc *crtc, |
772 | const struct drm_display_mode *mode) |
773 | { |
774 | struct tilcdc_drm_private *priv = crtc->dev->dev_private; |
775 | unsigned int bandwidth; |
776 | uint32_t hbp, hfp, hsw, vbp, vfp, vsw; |
777 | |
778 | /* |
779 | * check to see if the width is within the range that |
780 | * the LCD Controller physically supports |
781 | */ |
782 | if (mode->hdisplay > priv->max_width) |
783 | return MODE_VIRTUAL_X; |
784 | |
785 | /* width must be multiple of 16 */ |
786 | if (mode->hdisplay & 0xf) |
787 | return MODE_VIRTUAL_X; |
788 | |
789 | if (mode->vdisplay > 2048) |
790 | return MODE_VIRTUAL_Y; |
791 | |
792 | DBG("Processing mode %dx%d@%d with pixel clock %d" , |
793 | mode->hdisplay, mode->vdisplay, |
794 | drm_mode_vrefresh(mode), mode->clock); |
795 | |
796 | hbp = mode->htotal - mode->hsync_end; |
797 | hfp = mode->hsync_start - mode->hdisplay; |
798 | hsw = mode->hsync_end - mode->hsync_start; |
799 | vbp = mode->vtotal - mode->vsync_end; |
800 | vfp = mode->vsync_start - mode->vdisplay; |
801 | vsw = mode->vsync_end - mode->vsync_start; |
802 | |
803 | if ((hbp-1) & ~0x3ff) { |
804 | DBG("Pruning mode: Horizontal Back Porch out of range" ); |
805 | return MODE_HBLANK_WIDE; |
806 | } |
807 | |
808 | if ((hfp-1) & ~0x3ff) { |
809 | DBG("Pruning mode: Horizontal Front Porch out of range" ); |
810 | return MODE_HBLANK_WIDE; |
811 | } |
812 | |
813 | if ((hsw-1) & ~0x3ff) { |
814 | DBG("Pruning mode: Horizontal Sync Width out of range" ); |
815 | return MODE_HSYNC_WIDE; |
816 | } |
817 | |
818 | if (vbp & ~0xff) { |
819 | DBG("Pruning mode: Vertical Back Porch out of range" ); |
820 | return MODE_VBLANK_WIDE; |
821 | } |
822 | |
823 | if (vfp & ~0xff) { |
824 | DBG("Pruning mode: Vertical Front Porch out of range" ); |
825 | return MODE_VBLANK_WIDE; |
826 | } |
827 | |
828 | if ((vsw-1) & ~0x3f) { |
829 | DBG("Pruning mode: Vertical Sync Width out of range" ); |
830 | return MODE_VSYNC_WIDE; |
831 | } |
832 | |
833 | /* |
834 | * some devices have a maximum allowed pixel clock |
835 | * configured from the DT |
836 | */ |
837 | if (mode->clock > priv->max_pixelclock) { |
838 | DBG("Pruning mode: pixel clock too high" ); |
839 | return MODE_CLOCK_HIGH; |
840 | } |
841 | |
842 | /* |
843 | * some devices further limit the max horizontal resolution |
844 | * configured from the DT |
845 | */ |
846 | if (mode->hdisplay > priv->max_width) |
847 | return MODE_BAD_WIDTH; |
848 | |
849 | /* filter out modes that would require too much memory bandwidth: */ |
850 | bandwidth = mode->hdisplay * mode->vdisplay * |
851 | drm_mode_vrefresh(mode); |
852 | if (bandwidth > priv->max_bandwidth) { |
853 | DBG("Pruning mode: exceeds defined bandwidth limit" ); |
854 | return MODE_BAD; |
855 | } |
856 | |
857 | return MODE_OK; |
858 | } |
859 | |
860 | static const struct drm_crtc_helper_funcs tilcdc_crtc_helper_funcs = { |
861 | .mode_valid = tilcdc_crtc_mode_valid, |
862 | .mode_fixup = tilcdc_crtc_mode_fixup, |
863 | .atomic_check = tilcdc_crtc_atomic_check, |
864 | .atomic_enable = tilcdc_crtc_atomic_enable, |
865 | .atomic_disable = tilcdc_crtc_atomic_disable, |
866 | .atomic_flush = tilcdc_crtc_atomic_flush, |
867 | }; |
868 | |
869 | void tilcdc_crtc_set_panel_info(struct drm_crtc *crtc, |
870 | const struct tilcdc_panel_info *info) |
871 | { |
872 | struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); |
873 | tilcdc_crtc->info = info; |
874 | } |
875 | |
876 | void tilcdc_crtc_set_simulate_vesa_sync(struct drm_crtc *crtc, |
877 | bool simulate_vesa_sync) |
878 | { |
879 | struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); |
880 | |
881 | tilcdc_crtc->simulate_vesa_sync = simulate_vesa_sync; |
882 | } |
883 | |
884 | void tilcdc_crtc_update_clk(struct drm_crtc *crtc) |
885 | { |
886 | struct drm_device *dev = crtc->dev; |
887 | struct tilcdc_drm_private *priv = dev->dev_private; |
888 | struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); |
889 | |
890 | drm_modeset_lock(lock: &crtc->mutex, NULL); |
891 | if (tilcdc_crtc->lcd_fck_rate != clk_get_rate(clk: priv->clk)) { |
892 | if (tilcdc_crtc_is_on(crtc)) { |
893 | pm_runtime_get_sync(dev: dev->dev); |
894 | tilcdc_crtc_disable(crtc); |
895 | |
896 | tilcdc_crtc_set_clk(crtc); |
897 | |
898 | tilcdc_crtc_enable(crtc); |
899 | pm_runtime_put_sync(dev: dev->dev); |
900 | } |
901 | } |
902 | drm_modeset_unlock(lock: &crtc->mutex); |
903 | } |
904 | |
905 | #define SYNC_LOST_COUNT_LIMIT 50 |
906 | |
907 | irqreturn_t tilcdc_crtc_irq(struct drm_crtc *crtc) |
908 | { |
909 | struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); |
910 | struct drm_device *dev = crtc->dev; |
911 | struct tilcdc_drm_private *priv = dev->dev_private; |
912 | uint32_t stat, reg; |
913 | |
914 | stat = tilcdc_read_irqstatus(dev); |
915 | tilcdc_clear_irqstatus(dev, mask: stat); |
916 | |
917 | if (stat & LCDC_END_OF_FRAME0) { |
918 | bool skip_event = false; |
919 | ktime_t now; |
920 | |
921 | now = ktime_get(); |
922 | |
923 | spin_lock(lock: &tilcdc_crtc->irq_lock); |
924 | |
925 | tilcdc_crtc->last_vblank = now; |
926 | |
927 | if (tilcdc_crtc->next_fb) { |
928 | set_scanout(crtc, fb: tilcdc_crtc->next_fb); |
929 | tilcdc_crtc->next_fb = NULL; |
930 | skip_event = true; |
931 | } |
932 | |
933 | spin_unlock(lock: &tilcdc_crtc->irq_lock); |
934 | |
935 | drm_crtc_handle_vblank(crtc); |
936 | |
937 | if (!skip_event) { |
938 | struct drm_pending_vblank_event *event; |
939 | |
940 | spin_lock(lock: &dev->event_lock); |
941 | |
942 | event = tilcdc_crtc->event; |
943 | tilcdc_crtc->event = NULL; |
944 | if (event) |
945 | drm_crtc_send_vblank_event(crtc, e: event); |
946 | |
947 | spin_unlock(lock: &dev->event_lock); |
948 | } |
949 | |
950 | if (tilcdc_crtc->frame_intact) |
951 | tilcdc_crtc->sync_lost_count = 0; |
952 | else |
953 | tilcdc_crtc->frame_intact = true; |
954 | } |
955 | |
956 | if (stat & LCDC_FIFO_UNDERFLOW) |
957 | dev_err_ratelimited(dev->dev, "%s(0x%08x): FIFO underflow" , |
958 | __func__, stat); |
959 | |
960 | if (stat & LCDC_PL_LOAD_DONE) { |
961 | complete(&tilcdc_crtc->palette_loaded); |
962 | if (priv->rev == 1) |
963 | tilcdc_clear(dev, LCDC_RASTER_CTRL_REG, |
964 | LCDC_V1_PL_INT_ENA); |
965 | else |
966 | tilcdc_write(dev, LCDC_INT_ENABLE_CLR_REG, |
967 | LCDC_V2_PL_INT_ENA); |
968 | } |
969 | |
970 | if (stat & LCDC_SYNC_LOST) { |
971 | dev_err_ratelimited(dev->dev, "%s(0x%08x): Sync lost" , |
972 | __func__, stat); |
973 | tilcdc_crtc->frame_intact = false; |
974 | if (priv->rev == 1) { |
975 | reg = tilcdc_read(dev, LCDC_RASTER_CTRL_REG); |
976 | if (reg & LCDC_RASTER_ENABLE) { |
977 | tilcdc_clear(dev, LCDC_RASTER_CTRL_REG, |
978 | LCDC_RASTER_ENABLE); |
979 | tilcdc_set(dev, LCDC_RASTER_CTRL_REG, |
980 | LCDC_RASTER_ENABLE); |
981 | } |
982 | } else { |
983 | if (tilcdc_crtc->sync_lost_count++ > |
984 | SYNC_LOST_COUNT_LIMIT) { |
985 | dev_err(dev->dev, |
986 | "%s(0x%08x): Sync lost flood detected, recovering" , |
987 | __func__, stat); |
988 | queue_work(wq: system_wq, |
989 | work: &tilcdc_crtc->recover_work); |
990 | tilcdc_write(dev, LCDC_INT_ENABLE_CLR_REG, |
991 | LCDC_SYNC_LOST); |
992 | tilcdc_crtc->sync_lost_count = 0; |
993 | } |
994 | } |
995 | } |
996 | |
997 | if (stat & LCDC_FRAME_DONE) { |
998 | tilcdc_crtc->frame_done = true; |
999 | wake_up(&tilcdc_crtc->frame_done_wq); |
1000 | /* rev 1 lcdc appears to hang if irq is not disabled here */ |
1001 | if (priv->rev == 1) |
1002 | tilcdc_clear(dev, LCDC_RASTER_CTRL_REG, |
1003 | LCDC_V1_FRAME_DONE_INT_ENA); |
1004 | } |
1005 | |
1006 | /* For revision 2 only */ |
1007 | if (priv->rev == 2) { |
1008 | /* Indicate to LCDC that the interrupt service routine has |
1009 | * completed, see 13.3.6.1.6 in AM335x TRM. |
1010 | */ |
1011 | tilcdc_write(dev, LCDC_END_OF_INT_IND_REG, data: 0); |
1012 | } |
1013 | |
1014 | return IRQ_HANDLED; |
1015 | } |
1016 | |
1017 | int tilcdc_crtc_create(struct drm_device *dev) |
1018 | { |
1019 | struct tilcdc_drm_private *priv = dev->dev_private; |
1020 | struct tilcdc_crtc *tilcdc_crtc; |
1021 | struct drm_crtc *crtc; |
1022 | int ret; |
1023 | |
1024 | tilcdc_crtc = devm_kzalloc(dev: dev->dev, size: sizeof(*tilcdc_crtc), GFP_KERNEL); |
1025 | if (!tilcdc_crtc) |
1026 | return -ENOMEM; |
1027 | |
1028 | init_completion(x: &tilcdc_crtc->palette_loaded); |
1029 | tilcdc_crtc->palette_base = dmam_alloc_coherent(dev: dev->dev, |
1030 | TILCDC_PALETTE_SIZE, |
1031 | dma_handle: &tilcdc_crtc->palette_dma_handle, |
1032 | GFP_KERNEL | __GFP_ZERO); |
1033 | if (!tilcdc_crtc->palette_base) |
1034 | return -ENOMEM; |
1035 | *tilcdc_crtc->palette_base = TILCDC_PALETTE_FIRST_ENTRY; |
1036 | |
1037 | crtc = &tilcdc_crtc->base; |
1038 | |
1039 | ret = tilcdc_plane_init(dev, plane: &tilcdc_crtc->primary); |
1040 | if (ret < 0) |
1041 | goto fail; |
1042 | |
1043 | mutex_init(&tilcdc_crtc->enable_lock); |
1044 | |
1045 | init_waitqueue_head(&tilcdc_crtc->frame_done_wq); |
1046 | |
1047 | spin_lock_init(&tilcdc_crtc->irq_lock); |
1048 | INIT_WORK(&tilcdc_crtc->recover_work, tilcdc_crtc_recover_work); |
1049 | |
1050 | ret = drm_crtc_init_with_planes(dev, crtc, |
1051 | primary: &tilcdc_crtc->primary, |
1052 | NULL, |
1053 | funcs: &tilcdc_crtc_funcs, |
1054 | name: "tilcdc crtc" ); |
1055 | if (ret < 0) |
1056 | goto fail; |
1057 | |
1058 | drm_crtc_helper_add(crtc, funcs: &tilcdc_crtc_helper_funcs); |
1059 | |
1060 | if (priv->is_componentized) { |
1061 | crtc->port = of_graph_get_port_by_id(node: dev->dev->of_node, id: 0); |
1062 | if (!crtc->port) { /* This should never happen */ |
1063 | dev_err(dev->dev, "Port node not found in %pOF\n" , |
1064 | dev->dev->of_node); |
1065 | ret = -EINVAL; |
1066 | goto fail; |
1067 | } |
1068 | } |
1069 | |
1070 | priv->crtc = crtc; |
1071 | return 0; |
1072 | |
1073 | fail: |
1074 | tilcdc_crtc_destroy(crtc); |
1075 | return ret; |
1076 | } |
1077 | |