File Index
Files and directories
Sign in
FILE

mxsfb_kms.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/mxsfb/mxsfb_kms.c C
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 * Copyright (C) 2016 Marek Vasut <marex@denx.de>
  4 *
  5 * This code is based on drivers/video/fbdev/mxsfb.c :
  6 * Copyright (C) 2010 Juergen Beisert, Pengutronix
  7 * Copyright (C) 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved.
  8 * Copyright (C) 2008 Embedded Alley Solutions, Inc All Rights Reserved.
  9 */
 10
 11#include <linux/clk.h>
 12#include <linux/io.h>
 13#include <linux/iopoll.h>
 14#include <linux/media-bus-format.h>
 15#include <linux/pm_runtime.h>
 16#include <linux/spinlock.h>
 17
 18#include <drm/drm_atomic.h>
 19#include <drm/drm_atomic_helper.h>
 20#include <drm/drm_bridge.h>
 21#include <drm/drm_crtc.h>
 22#include <drm/drm_encoder.h>
 23#include <drm/drm_fb_dma_helper.h>
 24#include <drm/drm_fourcc.h>
 25#include <drm/drm_framebuffer.h>
 26#include <drm/drm_gem_atomic_helper.h>
 27#include <drm/drm_gem_dma_helper.h>
 28#include <drm/drm_plane.h>
 29#include <drm/drm_print.h>
 30#include <drm/drm_vblank.h>
 31
 32#include "mxsfb_drv.h"
 33#include "mxsfb_regs.h"
 34
 35/* 1 second delay should be plenty of time for block reset */
 36#define RESET_TIMEOUT		1000000
 37
 38/* -----------------------------------------------------------------------------
 39 * CRTC
 40 */
 41
 42static u32 set_hsync_pulse_width(struct mxsfb_drm_private *mxsfb, u32 val)
 43{
 44	return (val & mxsfb->devdata->hs_wdth_mask) <<
 45		mxsfb->devdata->hs_wdth_shift;
 46}
 47
 48/*
 49 * Setup the MXSFB registers for decoding the pixels out of the framebuffer and
 50 * outputting them on the bus.
 51 */
 52static void mxsfb_set_formats(struct mxsfb_drm_private *mxsfb,
 53			      const u32 bus_format)
 54{
 55	struct drm_device *drm = mxsfb->drm;
 56	const u32 format = mxsfb->crtc.primary->state->fb->format->format;
 57	u32 ctrl, ctrl1;
 58
 59	DRM_DEV_DEBUG_DRIVER(drm->dev, "Using bus_format: 0x%08X\n",
 60			     bus_format);
 61
 62	ctrl = CTRL_BYPASS_COUNT | CTRL_MASTER;
 63
 64	/* CTRL1 contains IRQ config and status bits, preserve those. */
 65	ctrl1 = readl(mxsfb->base + LCDC_CTRL1);
 66	ctrl1 &= CTRL1_CUR_FRAME_DONE_IRQ_EN | CTRL1_CUR_FRAME_DONE_IRQ;
 67
 68	switch (format) {
 69	case DRM_FORMAT_RGB565:
 70		dev_dbg(drm->dev, "Setting up RGB565 mode\n");
 71		ctrl |= CTRL_WORD_LENGTH_16;
 72		ctrl1 |= CTRL1_SET_BYTE_PACKAGING(0xf);
 73		break;
 74	case DRM_FORMAT_XRGB8888:
 75		dev_dbg(drm->dev, "Setting up XRGB8888 mode\n");
 76		ctrl |= CTRL_WORD_LENGTH_24;
 77		/* Do not use packed pixels = one pixel per word instead. */
 78		ctrl1 |= CTRL1_SET_BYTE_PACKAGING(0x7);
 79		break;
 80	}
 81
 82	switch (bus_format) {
 83	case MEDIA_BUS_FMT_RGB565_1X16:
 84		ctrl |= CTRL_BUS_WIDTH_16;
 85		break;
 86	case MEDIA_BUS_FMT_RGB666_1X18:
 87		ctrl |= CTRL_BUS_WIDTH_18;
 88		break;
 89	case MEDIA_BUS_FMT_RGB888_1X24:
 90		ctrl |= CTRL_BUS_WIDTH_24;
 91		break;
 92	default:
 93		dev_err(drm->dev, "Unknown media bus format 0x%x\n", bus_format);
 94		break;
 95	}
 96
 97	writel(ctrl1, mxsfb->base + LCDC_CTRL1);
 98	writel(ctrl, mxsfb->base + LCDC_CTRL);
 99}
100
101static void mxsfb_set_mode(struct mxsfb_drm_private *mxsfb, u32 bus_flags)
102{
103	struct drm_display_mode *m = &mxsfb->crtc.state->adjusted_mode;
104	u32 vdctrl0, vsync_pulse_len, hsync_pulse_len;
105
106	writel(TRANSFER_COUNT_SET_VCOUNT(m->crtc_vdisplay) |
107	       TRANSFER_COUNT_SET_HCOUNT(m->crtc_hdisplay),
108	       mxsfb->base + mxsfb->devdata->transfer_count);
109
110	vsync_pulse_len = m->crtc_vsync_end - m->crtc_vsync_start;
111
112	vdctrl0 = VDCTRL0_ENABLE_PRESENT |	/* Always in DOTCLOCK mode */
113		  VDCTRL0_VSYNC_PERIOD_UNIT |
114		  VDCTRL0_VSYNC_PULSE_WIDTH_UNIT |
115		  VDCTRL0_SET_VSYNC_PULSE_WIDTH(vsync_pulse_len);
116	if (m->flags & DRM_MODE_FLAG_PHSYNC)
117		vdctrl0 |= VDCTRL0_HSYNC_ACT_HIGH;
118	if (m->flags & DRM_MODE_FLAG_PVSYNC)
119		vdctrl0 |= VDCTRL0_VSYNC_ACT_HIGH;
120	/* Make sure Data Enable is high active by default */
121	if (!(bus_flags & DRM_BUS_FLAG_DE_LOW))
122		vdctrl0 |= VDCTRL0_ENABLE_ACT_HIGH;
123	/*
124	 * DRM_BUS_FLAG_PIXDATA_DRIVE_ defines are controller centric,
125	 * controllers VDCTRL0_DOTCLK is display centric.
126	 * Drive on positive edge       -> display samples on falling edge
127	 * DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE -> VDCTRL0_DOTCLK_ACT_FALLING
128	 */
129	if (bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE)
130		vdctrl0 |= VDCTRL0_DOTCLK_ACT_FALLING;
131
132	writel(vdctrl0, mxsfb->base + LCDC_VDCTRL0);
133
134	/* Frame length in lines. */
135	writel(m->crtc_vtotal, mxsfb->base + LCDC_VDCTRL1);
136
137	/* Line length in units of clocks or pixels. */
138	hsync_pulse_len = m->crtc_hsync_end - m->crtc_hsync_start;
139	writel(set_hsync_pulse_width(mxsfb, hsync_pulse_len) |
140	       VDCTRL2_SET_HSYNC_PERIOD(m->crtc_htotal),
141	       mxsfb->base + LCDC_VDCTRL2);
142
143	writel(SET_HOR_WAIT_CNT(m->crtc_htotal - m->crtc_hsync_start) |
144	       SET_VERT_WAIT_CNT(m->crtc_vtotal - m->crtc_vsync_start),
145	       mxsfb->base + LCDC_VDCTRL3);
146
147	writel(SET_DOTCLK_H_VALID_DATA_CNT(m->hdisplay),
148	       mxsfb->base + LCDC_VDCTRL4);
149
150}
151
152static void mxsfb_enable_controller(struct mxsfb_drm_private *mxsfb)
153{
154	u32 reg;
155
156	if (mxsfb->clk_disp_axi)
157		clk_prepare_enable(mxsfb->clk_disp_axi);
158	clk_prepare_enable(mxsfb->clk);
159
160	/* Increase number of outstanding requests on all supported IPs */
161	if (mxsfb->devdata->has_ctrl2) {
162		reg = readl(mxsfb->base + LCDC_V4_CTRL2);
163		reg &= ~CTRL2_SET_OUTSTANDING_REQS_MASK;
164		reg |= CTRL2_SET_OUTSTANDING_REQS_16;
165		writel(reg, mxsfb->base + LCDC_V4_CTRL2);
166	}
167
168	/* If it was disabled, re-enable the mode again */
169	writel(CTRL_DOTCLK_MODE, mxsfb->base + LCDC_CTRL + REG_SET);
170
171	/* Enable the SYNC signals first, then the DMA engine */
172	reg = readl(mxsfb->base + LCDC_VDCTRL4);
173	reg |= VDCTRL4_SYNC_SIGNALS_ON;
174	writel(reg, mxsfb->base + LCDC_VDCTRL4);
175
176	/*
177	 * Enable recovery on underflow.
178	 *
179	 * There is some sort of corner case behavior of the controller,
180	 * which could rarely be triggered at least on i.MX6SX connected
181	 * to 800x480 DPI panel and i.MX8MM connected to DPI->DSI->LVDS
182	 * bridged 1920x1080 panel (and likely on other setups too), where
183	 * the image on the panel shifts to the right and wraps around.
184	 * This happens either when the controller is enabled on boot or
185	 * even later during run time. The condition does not correct
186	 * itself automatically, i.e. the display image remains shifted.
187	 *
188	 * It seems this problem is known and is due to sporadic underflows
189	 * of the LCDIF FIFO. While the LCDIF IP does have underflow/overflow
190	 * IRQs, neither of the IRQs trigger and neither IRQ status bit is
191	 * asserted when this condition occurs.
192	 *
193	 * All known revisions of the LCDIF IP have CTRL1 RECOVER_ON_UNDERFLOW
194	 * bit, which is described in the reference manual since i.MX23 as
195	 * "
196	 *   Set this bit to enable the LCDIF block to recover in the next
197	 *   field/frame if there was an underflow in the current field/frame.
198	 * "
199	 * Enable this bit to mitigate the sporadic underflows.
200	 */
201	reg = readl(mxsfb->base + LCDC_CTRL1);
202	reg |= CTRL1_RECOVER_ON_UNDERFLOW;
203	writel(reg, mxsfb->base + LCDC_CTRL1);
204
205	writel(CTRL_RUN, mxsfb->base + LCDC_CTRL + REG_SET);
206}
207
208static void mxsfb_disable_controller(struct mxsfb_drm_private *mxsfb)
209{
210	u32 reg;
211
212	/*
213	 * Even if we disable the controller here, it will still continue
214	 * until its FIFOs are running out of data
215	 */
216	writel(CTRL_DOTCLK_MODE, mxsfb->base + LCDC_CTRL + REG_CLR);
217
218	readl_poll_timeout(mxsfb->base + LCDC_CTRL, reg, !(reg & CTRL_RUN),
219			   0, 1000);
220
221	reg = readl(mxsfb->base + LCDC_VDCTRL4);
222	reg &= ~VDCTRL4_SYNC_SIGNALS_ON;
223	writel(reg, mxsfb->base + LCDC_VDCTRL4);
224
225	clk_disable_unprepare(mxsfb->clk);
226	if (mxsfb->clk_disp_axi)
227		clk_disable_unprepare(mxsfb->clk_disp_axi);
228}
229
230/*
231 * Clear the bit and poll it cleared.  This is usually called with
232 * a reset address and mask being either SFTRST(bit 31) or CLKGATE
233 * (bit 30).
234 */
235static int clear_poll_bit(void __iomem *addr, u32 mask)
236{
237	u32 reg;
238
239	writel(mask, addr + REG_CLR);
240	return readl_poll_timeout(addr, reg, !(reg & mask), 0, RESET_TIMEOUT);
241}
242
243static int mxsfb_reset_block(struct mxsfb_drm_private *mxsfb)
244{
245	int ret;
246
247	/*
248	 * It seems, you can't re-program the controller if it is still
249	 * running. This may lead to shifted pictures (FIFO issue?), so
250	 * first stop the controller and drain its FIFOs.
251	 */
252
253	ret = clear_poll_bit(mxsfb->base + LCDC_CTRL, CTRL_SFTRST);
254	if (ret)
255		return ret;
256
257	writel(CTRL_CLKGATE, mxsfb->base + LCDC_CTRL + REG_CLR);
258
259	ret = clear_poll_bit(mxsfb->base + LCDC_CTRL, CTRL_SFTRST);
260	if (ret)
261		return ret;
262
263	ret = clear_poll_bit(mxsfb->base + LCDC_CTRL, CTRL_CLKGATE);
264	if (ret)
265		return ret;
266
267	/* Clear the FIFOs */
268	writel(CTRL1_FIFO_CLEAR, mxsfb->base + LCDC_CTRL1 + REG_SET);
269	readl(mxsfb->base + LCDC_CTRL1);
270	writel(CTRL1_FIFO_CLEAR, mxsfb->base + LCDC_CTRL1 + REG_CLR);
271	readl(mxsfb->base + LCDC_CTRL1);
272
273	if (mxsfb->devdata->has_overlay)
274		writel(0, mxsfb->base + LCDC_AS_CTRL);
275
276	return 0;
277}
278
279static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb,
280				     struct drm_bridge_state *bridge_state,
281				     const u32 bus_format)
282{
283	struct drm_device *drm = mxsfb->crtc.dev;
284	struct drm_display_mode *m = &mxsfb->crtc.state->adjusted_mode;
285	u32 bus_flags = mxsfb->connector->display_info.bus_flags;
286	int err;
287
288	if (mxsfb->bridge && mxsfb->bridge->timings)
289		bus_flags = mxsfb->bridge->timings->input_bus_flags;
290	else if (bridge_state)
291		bus_flags = bridge_state->input_bus_cfg.flags;
292
293	DRM_DEV_DEBUG_DRIVER(drm->dev, "Pixel clock: %dkHz (actual: %dkHz)\n",
294			     m->crtc_clock,
295			     (int)(clk_get_rate(mxsfb->clk) / 1000));
296	DRM_DEV_DEBUG_DRIVER(drm->dev, "Connector bus_flags: 0x%08X\n",
297			     bus_flags);
298	DRM_DEV_DEBUG_DRIVER(drm->dev, "Mode flags: 0x%08X\n", m->flags);
299
300	/* Mandatory eLCDIF reset as per the Reference Manual */
301	err = mxsfb_reset_block(mxsfb);
302	if (err)
303		return;
304
305	mxsfb_set_formats(mxsfb, bus_format);
306
307	clk_set_rate(mxsfb->clk, m->crtc_clock * 1000);
308
309	mxsfb_set_mode(mxsfb, bus_flags);
310}
311
312static int mxsfb_crtc_atomic_check(struct drm_crtc *crtc,
313				   struct drm_atomic_state *state)
314{
315	struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state,
316									  crtc);
317	bool has_primary = crtc_state->plane_mask &
318			   drm_plane_mask(crtc->primary);
319
320	/* The primary plane has to be enabled when the CRTC is active. */
321	if (crtc_state->active && !has_primary)
322		return -EINVAL;
323
324	/* TODO: Is this needed ? */
325	return drm_atomic_add_affected_planes(state, crtc);
326}
327
328static void mxsfb_crtc_atomic_flush(struct drm_crtc *crtc,
329				    struct drm_atomic_state *state)
330{
331	struct drm_pending_vblank_event *event;
332
333	event = crtc->state->event;
334	crtc->state->event = NULL;
335
336	if (!event)
337		return;
338
339	spin_lock_irq(&crtc->dev->event_lock);
340	if (drm_crtc_vblank_get(crtc) == 0)
341		drm_crtc_arm_vblank_event(crtc, event);
342	else
343		drm_crtc_send_vblank_event(crtc, event);
344	spin_unlock_irq(&crtc->dev->event_lock);
345}
346
347static void mxsfb_crtc_atomic_enable(struct drm_crtc *crtc,
348				     struct drm_atomic_state *state)
349{
350	struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(crtc->dev);
351	struct drm_plane_state *new_pstate = drm_atomic_get_new_plane_state(state,
352									    crtc->primary);
353	struct drm_bridge_state *bridge_state = NULL;
354	struct drm_device *drm = mxsfb->drm;
355	u32 bus_format = 0;
356	dma_addr_t dma_addr;
357
358	pm_runtime_get_sync(drm->dev);
359	mxsfb_enable_axi_clk(mxsfb);
360
361	drm_crtc_vblank_on(crtc);
362
363	/* If there is a bridge attached to the LCDIF, use its bus format */
364	if (mxsfb->bridge) {
365		bridge_state =
366			drm_atomic_get_new_bridge_state(state,
367							mxsfb->bridge);
368		if (!bridge_state)
369			bus_format = MEDIA_BUS_FMT_FIXED;
370		else
371			bus_format = bridge_state->input_bus_cfg.format;
372
373		if (bus_format == MEDIA_BUS_FMT_FIXED) {
374			dev_warn_once(drm->dev,
375				      "Bridge does not provide bus format, assuming MEDIA_BUS_FMT_RGB888_1X24.\n"
376				      "Please fix bridge driver by handling atomic_get_input_bus_fmts.\n");
377			bus_format = MEDIA_BUS_FMT_RGB888_1X24;
378		}
379	}
380
381	/* If there is no bridge, use bus format from connector */
382	if (!bus_format && mxsfb->connector->display_info.num_bus_formats)
383		bus_format = mxsfb->connector->display_info.bus_formats[0];
384
385	/* If all else fails, default to RGB888_1X24 */
386	if (!bus_format)
387		bus_format = MEDIA_BUS_FMT_RGB888_1X24;
388
389	mxsfb_crtc_mode_set_nofb(mxsfb, bridge_state, bus_format);
390
391	/* Write cur_buf as well to avoid an initial corrupt frame */
392	dma_addr = drm_fb_dma_get_gem_addr(new_pstate->fb, new_pstate, 0);
393	if (dma_addr) {
394		writel(dma_addr, mxsfb->base + mxsfb->devdata->cur_buf);
395		writel(dma_addr, mxsfb->base + mxsfb->devdata->next_buf);
396	}
397
398	mxsfb_enable_controller(mxsfb);
399}
400
401static void mxsfb_crtc_atomic_disable(struct drm_crtc *crtc,
402				      struct drm_atomic_state *state)
403{
404	struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(crtc->dev);
405	struct drm_device *drm = mxsfb->drm;
406	struct drm_pending_vblank_event *event;
407
408	mxsfb_disable_controller(mxsfb);
409
410	spin_lock_irq(&drm->event_lock);
411	event = crtc->state->event;
412	if (event) {
413		crtc->state->event = NULL;
414		drm_crtc_send_vblank_event(crtc, event);
415	}
416	spin_unlock_irq(&drm->event_lock);
417
418	drm_crtc_vblank_off(crtc);
419
420	mxsfb_disable_axi_clk(mxsfb);
421	pm_runtime_put_sync(drm->dev);
422}
423
424static int mxsfb_crtc_enable_vblank(struct drm_crtc *crtc)
425{
426	struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(crtc->dev);
427
428	/* Clear and enable VBLANK IRQ */
429	writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR);
430	writel(CTRL1_CUR_FRAME_DONE_IRQ_EN, mxsfb->base + LCDC_CTRL1 + REG_SET);
431
432	return 0;
433}
434
435static void mxsfb_crtc_disable_vblank(struct drm_crtc *crtc)
436{
437	struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(crtc->dev);
438
439	/* Disable and clear VBLANK IRQ */
440	writel(CTRL1_CUR_FRAME_DONE_IRQ_EN, mxsfb->base + LCDC_CTRL1 + REG_CLR);
441	writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR);
442}
443
444static int mxsfb_crtc_set_crc_source(struct drm_crtc *crtc, const char *source)
445{
446	struct mxsfb_drm_private *mxsfb;
447
448	if (!crtc)
449		return -ENODEV;
450
451	mxsfb = to_mxsfb_drm_private(crtc->dev);
452
453	if (source && strcmp(source, "auto") == 0)
454		mxsfb->crc_active = true;
455	else if (!source)
456		mxsfb->crc_active = false;
457	else
458		return -EINVAL;
459
460	return 0;
461}
462
463static int mxsfb_crtc_verify_crc_source(struct drm_crtc *crtc,
464					const char *source, size_t *values_cnt)
465{
466	if (!crtc)
467		return -ENODEV;
468
469	if (source && strcmp(source, "auto") != 0) {
470		DRM_DEBUG_DRIVER("Unknown CRC source %s for %s\n",
471				 source, crtc->name);
472		return -EINVAL;
473	}
474
475	*values_cnt = 1;
476	return 0;
477}
478
479static const struct drm_crtc_helper_funcs mxsfb_crtc_helper_funcs = {
480	.atomic_check = mxsfb_crtc_atomic_check,
481	.atomic_flush = mxsfb_crtc_atomic_flush,
482	.atomic_enable = mxsfb_crtc_atomic_enable,
483	.atomic_disable = mxsfb_crtc_atomic_disable,
484};
485
486static const struct drm_crtc_funcs mxsfb_crtc_funcs = {
487	.reset = drm_atomic_helper_crtc_reset,
488	.destroy = drm_crtc_cleanup,
489	.set_config = drm_atomic_helper_set_config,
490	.page_flip = drm_atomic_helper_page_flip,
491	.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
492	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
493	.enable_vblank = mxsfb_crtc_enable_vblank,
494	.disable_vblank = mxsfb_crtc_disable_vblank,
495};
496
497static const struct drm_crtc_funcs mxsfb_crtc_with_crc_funcs = {
498	.reset = drm_atomic_helper_crtc_reset,
499	.destroy = drm_crtc_cleanup,
500	.set_config = drm_atomic_helper_set_config,
501	.page_flip = drm_atomic_helper_page_flip,
502	.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
503	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
504	.enable_vblank = mxsfb_crtc_enable_vblank,
505	.disable_vblank = mxsfb_crtc_disable_vblank,
506	.set_crc_source = mxsfb_crtc_set_crc_source,
507	.verify_crc_source = mxsfb_crtc_verify_crc_source,
508};
509
510/* -----------------------------------------------------------------------------
511 * Encoder
512 */
513
514static const struct drm_encoder_funcs mxsfb_encoder_funcs = {
515	.destroy = drm_encoder_cleanup,
516};
517
518/* -----------------------------------------------------------------------------
519 * Planes
520 */
521
522static int mxsfb_plane_atomic_check(struct drm_plane *plane,
523				    struct drm_atomic_state *state)
524{
525	struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state,
526									     plane);
527	struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(plane->dev);
528	struct drm_crtc_state *crtc_state;
529
530	crtc_state = drm_atomic_get_new_crtc_state(state,
531						   &mxsfb->crtc);
532
533	return drm_atomic_helper_check_plane_state(plane_state, crtc_state,
534						   DRM_PLANE_NO_SCALING,
535						   DRM_PLANE_NO_SCALING,
536						   false, true);
537}
538
539static void mxsfb_plane_primary_atomic_update(struct drm_plane *plane,
540					      struct drm_atomic_state *state)
541{
542	struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(plane->dev);
543	struct drm_plane_state *new_pstate = drm_atomic_get_new_plane_state(state,
544									    plane);
545	dma_addr_t dma_addr;
546
547	dma_addr = drm_fb_dma_get_gem_addr(new_pstate->fb, new_pstate, 0);
548	if (dma_addr)
549		writel(dma_addr, mxsfb->base + mxsfb->devdata->next_buf);
550}
551
552static void mxsfb_plane_overlay_atomic_update(struct drm_plane *plane,
553					      struct drm_atomic_state *state)
554{
555	struct drm_plane_state *old_pstate = drm_atomic_get_old_plane_state(state,
556									    plane);
557	struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(plane->dev);
558	struct drm_plane_state *new_pstate = drm_atomic_get_new_plane_state(state,
559									    plane);
560	dma_addr_t dma_addr;
561	u32 ctrl;
562
563	dma_addr = drm_fb_dma_get_gem_addr(new_pstate->fb, new_pstate, 0);
564	if (!dma_addr) {
565		writel(0, mxsfb->base + LCDC_AS_CTRL);
566		return;
567	}
568
569	/*
570	 * HACK: The hardware seems to output 64 bytes of data of unknown
571	 * origin, and then to proceed with the framebuffer. Until the reason
572	 * is understood, live with the 16 initial invalid pixels on the first
573	 * line and start 64 bytes within the framebuffer.
574	 */
575	dma_addr += 64;
576
577	writel(dma_addr, mxsfb->base + LCDC_AS_NEXT_BUF);
578
579	/*
580	 * If the plane was previously disabled, write LCDC_AS_BUF as well to
581	 * provide the first buffer.
582	 */
583	if (!old_pstate->fb)
584		writel(dma_addr, mxsfb->base + LCDC_AS_BUF);
585
586	ctrl = AS_CTRL_AS_ENABLE | AS_CTRL_ALPHA(255);
587
588	switch (new_pstate->fb->format->format) {
589	case DRM_FORMAT_XRGB4444:
590		ctrl |= AS_CTRL_FORMAT_RGB444 | AS_CTRL_ALPHA_CTRL_OVERRIDE;
591		break;
592	case DRM_FORMAT_ARGB4444:
593		ctrl |= AS_CTRL_FORMAT_ARGB4444 | AS_CTRL_ALPHA_CTRL_EMBEDDED;
594		break;
595	case DRM_FORMAT_XRGB1555:
596		ctrl |= AS_CTRL_FORMAT_RGB555 | AS_CTRL_ALPHA_CTRL_OVERRIDE;
597		break;
598	case DRM_FORMAT_ARGB1555:
599		ctrl |= AS_CTRL_FORMAT_ARGB1555 | AS_CTRL_ALPHA_CTRL_EMBEDDED;
600		break;
601	case DRM_FORMAT_RGB565:
602		ctrl |= AS_CTRL_FORMAT_RGB565 | AS_CTRL_ALPHA_CTRL_OVERRIDE;
603		break;
604	case DRM_FORMAT_XRGB8888:
605		ctrl |= AS_CTRL_FORMAT_RGB888 | AS_CTRL_ALPHA_CTRL_OVERRIDE;
606		break;
607	case DRM_FORMAT_ARGB8888:
608		ctrl |= AS_CTRL_FORMAT_ARGB8888 | AS_CTRL_ALPHA_CTRL_EMBEDDED;
609		break;
610	}
611
612	writel(ctrl, mxsfb->base + LCDC_AS_CTRL);
613}
614
615static void mxsfb_plane_overlay_atomic_disable(struct drm_plane *plane,
616					       struct drm_atomic_state *state)
617{
618	struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(plane->dev);
619
620	writel(0, mxsfb->base + LCDC_AS_CTRL);
621}
622
623static bool mxsfb_format_mod_supported(struct drm_plane *plane,
624				       uint32_t format,
625				       uint64_t modifier)
626{
627	return modifier == DRM_FORMAT_MOD_LINEAR;
628}
629
630static const struct drm_plane_helper_funcs mxsfb_plane_primary_helper_funcs = {
631	.atomic_check = mxsfb_plane_atomic_check,
632	.atomic_update = mxsfb_plane_primary_atomic_update,
633};
634
635static const struct drm_plane_helper_funcs mxsfb_plane_overlay_helper_funcs = {
636	.atomic_check = mxsfb_plane_atomic_check,
637	.atomic_update = mxsfb_plane_overlay_atomic_update,
638	.atomic_disable = mxsfb_plane_overlay_atomic_disable,
639};
640
641static const struct drm_plane_funcs mxsfb_plane_funcs = {
642	.format_mod_supported	= mxsfb_format_mod_supported,
643	.update_plane		= drm_atomic_helper_update_plane,
644	.disable_plane		= drm_atomic_helper_disable_plane,
645	.destroy		= drm_plane_cleanup,
646	.reset			= drm_atomic_helper_plane_reset,
647	.atomic_duplicate_state	= drm_atomic_helper_plane_duplicate_state,
648	.atomic_destroy_state	= drm_atomic_helper_plane_destroy_state,
649};
650
651static const uint32_t mxsfb_primary_plane_formats[] = {
652	DRM_FORMAT_RGB565,
653	DRM_FORMAT_XRGB8888,
654};
655
656static const uint32_t mxsfb_overlay_plane_formats[] = {
657	DRM_FORMAT_XRGB4444,
658	DRM_FORMAT_ARGB4444,
659	DRM_FORMAT_XRGB1555,
660	DRM_FORMAT_ARGB1555,
661	DRM_FORMAT_RGB565,
662	DRM_FORMAT_XRGB8888,
663	DRM_FORMAT_ARGB8888,
664};
665
666static const uint64_t mxsfb_modifiers[] = {
667	DRM_FORMAT_MOD_LINEAR,
668	DRM_FORMAT_MOD_INVALID
669};
670
671/* -----------------------------------------------------------------------------
672 * Initialization
673 */
674
675int mxsfb_kms_init(struct mxsfb_drm_private *mxsfb)
676{
677	struct drm_encoder *encoder = &mxsfb->encoder;
678	struct drm_crtc *crtc = &mxsfb->crtc;
679	int ret;
680
681	drm_plane_helper_add(&mxsfb->planes.primary,
682			     &mxsfb_plane_primary_helper_funcs);
683	ret = drm_universal_plane_init(mxsfb->drm, &mxsfb->planes.primary, 1,
684				       &mxsfb_plane_funcs,
685				       mxsfb_primary_plane_formats,
686				       ARRAY_SIZE(mxsfb_primary_plane_formats),
687				       mxsfb_modifiers, DRM_PLANE_TYPE_PRIMARY,
688				       NULL);
689	if (ret)
690		return ret;
691
692	if (mxsfb->devdata->has_overlay) {
693		drm_plane_helper_add(&mxsfb->planes.overlay,
694				     &mxsfb_plane_overlay_helper_funcs);
695		ret = drm_universal_plane_init(mxsfb->drm,
696					       &mxsfb->planes.overlay, 1,
697					       &mxsfb_plane_funcs,
698					       mxsfb_overlay_plane_formats,
699					       ARRAY_SIZE(mxsfb_overlay_plane_formats),
700					       mxsfb_modifiers, DRM_PLANE_TYPE_OVERLAY,
701					       NULL);
702		if (ret)
703			return ret;
704	}
705
706	drm_crtc_helper_add(crtc, &mxsfb_crtc_helper_funcs);
707	if (mxsfb->devdata->has_crc32) {
708		ret = drm_crtc_init_with_planes(mxsfb->drm, crtc,
709						&mxsfb->planes.primary, NULL,
710						&mxsfb_crtc_with_crc_funcs,
711						NULL);
712	} else {
713		ret = drm_crtc_init_with_planes(mxsfb->drm, crtc,
714						&mxsfb->planes.primary, NULL,
715						&mxsfb_crtc_funcs, NULL);
716	}
717	if (ret)
718		return ret;
719
720	encoder->possible_crtcs = drm_crtc_mask(crtc);
721	return drm_encoder_init(mxsfb->drm, encoder, &mxsfb_encoder_funcs,
722				DRM_MODE_ENCODER_NONE, NULL);
723}
~/ Read-only file preview.