Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * i.MX drm driver - parallel display implementation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Copyright (C) 2012 Sascha Hauer, Pengutronix
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) #include <linux/component.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/videodev2.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <video/of_display_timing.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <drm/drm_atomic_helper.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <drm/drm_bridge.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <drm/drm_fb_helper.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <drm/drm_of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include <drm/drm_panel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #include <drm/drm_probe_helper.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #include <drm/drm_simple_kms_helper.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #include "imx-drm.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) struct imx_parallel_display {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 	struct drm_connector connector;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 	struct drm_encoder encoder;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 	struct drm_bridge bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 	struct device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 	void *edid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 	u32 bus_format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 	u32 bus_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 	struct drm_display_mode mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 	struct drm_panel *panel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 	struct drm_bridge *next_bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) static inline struct imx_parallel_display *con_to_imxpd(struct drm_connector *c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	return container_of(c, struct imx_parallel_display, connector);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) static inline struct imx_parallel_display *bridge_to_imxpd(struct drm_bridge *b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 	return container_of(b, struct imx_parallel_display, bridge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) static int imx_pd_connector_get_modes(struct drm_connector *connector)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	struct imx_parallel_display *imxpd = con_to_imxpd(connector);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 	struct device_node *np = imxpd->dev->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	int num_modes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 	num_modes = drm_panel_get_modes(imxpd->panel, connector);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	if (num_modes > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 		return num_modes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 	if (imxpd->edid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 		drm_connector_update_edid_property(connector, imxpd->edid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 		num_modes = drm_add_edid_modes(connector, imxpd->edid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 	if (np) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 		struct drm_display_mode *mode = drm_mode_create(connector->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 		int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 		if (!mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 		ret = of_get_drm_display_mode(np, &imxpd->mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 					      &imxpd->bus_flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 					      OF_USE_NATIVE_MODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 		if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 			return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 		drm_mode_copy(mode, &imxpd->mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 		mode->type |= DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 		drm_mode_probed_add(connector, mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 		num_modes++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 	return num_modes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) static void imx_pd_bridge_enable(struct drm_bridge *bridge)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	struct imx_parallel_display *imxpd = bridge_to_imxpd(bridge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	drm_panel_prepare(imxpd->panel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	drm_panel_enable(imxpd->panel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) static void imx_pd_bridge_disable(struct drm_bridge *bridge)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	struct imx_parallel_display *imxpd = bridge_to_imxpd(bridge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	drm_panel_disable(imxpd->panel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	drm_panel_unprepare(imxpd->panel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) static const u32 imx_pd_bus_fmts[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	MEDIA_BUS_FMT_RGB888_1X24,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	MEDIA_BUS_FMT_BGR888_1X24,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	MEDIA_BUS_FMT_GBR888_1X24,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	MEDIA_BUS_FMT_RGB666_1X18,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	MEDIA_BUS_FMT_RGB666_1X24_CPADHI,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	MEDIA_BUS_FMT_RGB565_1X16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) static u32 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) imx_pd_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 					 struct drm_bridge_state *bridge_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 					 struct drm_crtc_state *crtc_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 					 struct drm_connector_state *conn_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 					 unsigned int *num_output_fmts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	struct drm_display_info *di = &conn_state->connector->display_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 	struct imx_parallel_display *imxpd = bridge_to_imxpd(bridge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	u32 *output_fmts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	if (!imxpd->bus_format && !di->num_bus_formats) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 		*num_output_fmts = ARRAY_SIZE(imx_pd_bus_fmts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 		return kmemdup(imx_pd_bus_fmts, sizeof(imx_pd_bus_fmts),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 			       GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	*num_output_fmts = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	output_fmts = kmalloc(sizeof(*output_fmts), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	if (!output_fmts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	if (!imxpd->bus_format && di->num_bus_formats)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 		output_fmts[0] = di->bus_formats[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 		output_fmts[0] = imxpd->bus_format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 	return output_fmts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) static bool imx_pd_format_supported(u32 output_fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 	unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 	for (i = 0; i < ARRAY_SIZE(imx_pd_bus_fmts); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 		if (imx_pd_bus_fmts[i] == output_fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 			return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 	return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) static u32 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) imx_pd_bridge_atomic_get_input_bus_fmts(struct drm_bridge *bridge,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 					struct drm_bridge_state *bridge_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 					struct drm_crtc_state *crtc_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 					struct drm_connector_state *conn_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 					u32 output_fmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 					unsigned int *num_input_fmts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	struct imx_parallel_display *imxpd = bridge_to_imxpd(bridge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 	u32 *input_fmts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 	 * If the next bridge does not support bus format negotiation, let's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 	 * use the static bus format definition (imxpd->bus_format) if it's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 	 * specified, RGB888 when it's not.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 	if (output_fmt == MEDIA_BUS_FMT_FIXED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 		output_fmt = imxpd->bus_format ? : MEDIA_BUS_FMT_RGB888_1X24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 	/* Now make sure the requested output format is supported. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	if ((imxpd->bus_format && imxpd->bus_format != output_fmt) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 	    !imx_pd_format_supported(output_fmt)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 		*num_input_fmts = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 	*num_input_fmts = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 	input_fmts = kmalloc(sizeof(*input_fmts), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	if (!input_fmts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 	input_fmts[0] = output_fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 	return input_fmts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) static int imx_pd_bridge_atomic_check(struct drm_bridge *bridge,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 				      struct drm_bridge_state *bridge_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 				      struct drm_crtc_state *crtc_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 				      struct drm_connector_state *conn_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 	struct imx_crtc_state *imx_crtc_state = to_imx_crtc_state(crtc_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 	struct drm_display_info *di = &conn_state->connector->display_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 	struct imx_parallel_display *imxpd = bridge_to_imxpd(bridge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 	struct drm_bridge_state *next_bridge_state = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 	struct drm_bridge *next_bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 	u32 bus_flags, bus_fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 	next_bridge = drm_bridge_get_next_bridge(bridge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 	if (next_bridge)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 		next_bridge_state = drm_atomic_get_new_bridge_state(crtc_state->state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 								    next_bridge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 	if (next_bridge_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 		bus_flags = next_bridge_state->input_bus_cfg.flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 	else if (di->num_bus_formats)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 		bus_flags = di->bus_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 		bus_flags = imxpd->bus_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 	bus_fmt = bridge_state->input_bus_cfg.format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 	if (!imx_pd_format_supported(bus_fmt))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 	bridge_state->output_bus_cfg.flags = bus_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 	bridge_state->input_bus_cfg.flags = bus_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 	imx_crtc_state->bus_flags = bus_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 	imx_crtc_state->bus_format = bridge_state->input_bus_cfg.format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 	imx_crtc_state->di_hsync_pin = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 	imx_crtc_state->di_vsync_pin = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) static const struct drm_connector_funcs imx_pd_connector_funcs = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 	.fill_modes = drm_helper_probe_single_connector_modes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 	.destroy = imx_drm_connector_destroy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 	.reset = drm_atomic_helper_connector_reset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) static const struct drm_connector_helper_funcs imx_pd_connector_helper_funcs = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 	.get_modes = imx_pd_connector_get_modes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) static const struct drm_bridge_funcs imx_pd_bridge_funcs = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 	.enable = imx_pd_bridge_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 	.disable = imx_pd_bridge_disable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 	.atomic_reset = drm_atomic_helper_bridge_reset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 	.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 	.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 	.atomic_check = imx_pd_bridge_atomic_check,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 	.atomic_get_input_bus_fmts = imx_pd_bridge_atomic_get_input_bus_fmts,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 	.atomic_get_output_bus_fmts = imx_pd_bridge_atomic_get_output_bus_fmts,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) static int imx_pd_register(struct drm_device *drm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 	struct imx_parallel_display *imxpd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 	struct drm_encoder *encoder = &imxpd->encoder;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 	ret = imx_drm_encoder_parse_of(drm, encoder, imxpd->dev->of_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 	/* set the connector's dpms to OFF so that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 	 * drm_helper_connector_dpms() won't return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 	 * immediately since the current state is ON
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 	 * at this point.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 	imxpd->connector.dpms = DRM_MODE_DPMS_OFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 	drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_NONE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 	imxpd->bridge.funcs = &imx_pd_bridge_funcs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 	drm_bridge_attach(encoder, &imxpd->bridge, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 	if (!imxpd->next_bridge) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 		drm_connector_helper_add(&imxpd->connector,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 				&imx_pd_connector_helper_funcs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 		drm_connector_init(drm, &imxpd->connector,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 				   &imx_pd_connector_funcs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 				   DRM_MODE_CONNECTOR_DPI);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 	if (imxpd->next_bridge) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 		ret = drm_bridge_attach(encoder, imxpd->next_bridge,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 					&imxpd->bridge, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 		if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 			dev_err(imxpd->dev, "failed to attach bridge: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 				ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 			return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 		drm_connector_attach_encoder(&imxpd->connector, encoder);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) static int imx_pd_bind(struct device *dev, struct device *master, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 	struct drm_device *drm = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 	struct device_node *np = dev->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 	const u8 *edidp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 	struct imx_parallel_display *imxpd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 	int edid_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 	u32 bus_format = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 	const char *fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 	imxpd = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 	memset(imxpd, 0, sizeof(*imxpd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 	/* port@1 is the output port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 	ret = drm_of_find_panel_or_bridge(np, 1, 0, &imxpd->panel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 					  &imxpd->next_bridge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 	if (ret && ret != -ENODEV)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 	edidp = of_get_property(np, "edid", &edid_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 	if (edidp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 		imxpd->edid = devm_kmemdup(dev, edidp, edid_len, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 	ret = of_property_read_string(np, "interface-pix-fmt", &fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 	if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 		if (!strcmp(fmt, "rgb24"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 			bus_format = MEDIA_BUS_FMT_RGB888_1X24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 		else if (!strcmp(fmt, "rgb565"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 			bus_format = MEDIA_BUS_FMT_RGB565_1X16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 		else if (!strcmp(fmt, "bgr666"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 			bus_format = MEDIA_BUS_FMT_RGB666_1X18;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 		else if (!strcmp(fmt, "lvds666"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 			bus_format = MEDIA_BUS_FMT_RGB666_1X24_CPADHI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 	imxpd->bus_format = bus_format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 	imxpd->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 	ret = imx_pd_register(drm, imxpd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) static const struct component_ops imx_pd_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 	.bind	= imx_pd_bind,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) static int imx_pd_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 	struct imx_parallel_display *imxpd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 	imxpd = devm_kzalloc(&pdev->dev, sizeof(*imxpd), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 	if (!imxpd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 	platform_set_drvdata(pdev, imxpd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 	return component_add(&pdev->dev, &imx_pd_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) static int imx_pd_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 	component_del(&pdev->dev, &imx_pd_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) static const struct of_device_id imx_pd_dt_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 	{ .compatible = "fsl,imx-parallel-display", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 	{ /* sentinel */ }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) MODULE_DEVICE_TABLE(of, imx_pd_dt_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) static struct platform_driver imx_pd_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 	.probe		= imx_pd_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 	.remove		= imx_pd_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 	.driver		= {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 		.of_match_table = imx_pd_dt_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 		.name	= "imx-parallel-display",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) module_platform_driver(imx_pd_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) MODULE_DESCRIPTION("i.MX parallel display driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) MODULE_AUTHOR("Sascha Hauer, Pengutronix");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) MODULE_ALIAS("platform:imx-parallel-display");