Linux Audio

Check our new training course

Real-Time Linux with PREEMPT_RT training

Feb 18-20, 2025
Register
Loading...
Note: File does not exist in v4.6.
  1// SPDX-License-Identifier: GPL-2.0+
  2/*
  3 * Copyright (C) 2012 Sascha Hauer, Pengutronix
  4 * Copyright 2019,2020,2022 NXP
  5 */
  6
  7#include <linux/media-bus-format.h>
  8#include <linux/mfd/syscon.h>
  9#include <linux/of.h>
 10#include <linux/regmap.h>
 11
 12#include <drm/drm_bridge.h>
 13#include <drm/drm_of.h>
 14#include <drm/drm_print.h>
 15
 16#include "imx-ldb-helper.h"
 17
 18bool ldb_channel_is_single_link(struct ldb_channel *ldb_ch)
 19{
 20	return ldb_ch->link_type == LDB_CH_SINGLE_LINK;
 21}
 22
 23bool ldb_channel_is_split_link(struct ldb_channel *ldb_ch)
 24{
 25	return ldb_ch->link_type == LDB_CH_DUAL_LINK_EVEN_ODD_PIXELS ||
 26	       ldb_ch->link_type == LDB_CH_DUAL_LINK_ODD_EVEN_PIXELS;
 27}
 28
 29int ldb_bridge_atomic_check_helper(struct drm_bridge *bridge,
 30				   struct drm_bridge_state *bridge_state,
 31				   struct drm_crtc_state *crtc_state,
 32				   struct drm_connector_state *conn_state)
 33{
 34	struct ldb_channel *ldb_ch = bridge->driver_private;
 35
 36	ldb_ch->in_bus_format = bridge_state->input_bus_cfg.format;
 37	ldb_ch->out_bus_format = bridge_state->output_bus_cfg.format;
 38
 39	return 0;
 40}
 41
 42void ldb_bridge_mode_set_helper(struct drm_bridge *bridge,
 43				const struct drm_display_mode *mode,
 44				const struct drm_display_mode *adjusted_mode)
 45{
 46	struct ldb_channel *ldb_ch = bridge->driver_private;
 47	struct ldb *ldb = ldb_ch->ldb;
 48	bool is_split = ldb_channel_is_split_link(ldb_ch);
 49
 50	if (is_split)
 51		ldb->ldb_ctrl |= LDB_SPLIT_MODE_EN;
 52
 53	switch (ldb_ch->out_bus_format) {
 54	case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
 55		break;
 56	case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG:
 57		if (ldb_ch->chno == 0 || is_split)
 58			ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH0_24;
 59		if (ldb_ch->chno == 1 || is_split)
 60			ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH1_24;
 61		break;
 62	case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:
 63		if (ldb_ch->chno == 0 || is_split)
 64			ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH0_24 |
 65					 LDB_BIT_MAP_CH0_JEIDA;
 66		if (ldb_ch->chno == 1 || is_split)
 67			ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH1_24 |
 68					 LDB_BIT_MAP_CH1_JEIDA;
 69		break;
 70	}
 71}
 72
 73void ldb_bridge_enable_helper(struct drm_bridge *bridge)
 74{
 75	struct ldb_channel *ldb_ch = bridge->driver_private;
 76	struct ldb *ldb = ldb_ch->ldb;
 77
 78	/*
 79	 * Platform specific bridge drivers should set ldb_ctrl properly
 80	 * for the enablement, so just write the ctrl_reg here.
 81	 */
 82	regmap_write(ldb->regmap, ldb->ctrl_reg, ldb->ldb_ctrl);
 83}
 84
 85void ldb_bridge_disable_helper(struct drm_bridge *bridge)
 86{
 87	struct ldb_channel *ldb_ch = bridge->driver_private;
 88	struct ldb *ldb = ldb_ch->ldb;
 89	bool is_split = ldb_channel_is_split_link(ldb_ch);
 90
 91	if (ldb_ch->chno == 0 || is_split)
 92		ldb->ldb_ctrl &= ~LDB_CH0_MODE_EN_MASK;
 93	if (ldb_ch->chno == 1 || is_split)
 94		ldb->ldb_ctrl &= ~LDB_CH1_MODE_EN_MASK;
 95
 96	regmap_write(ldb->regmap, ldb->ctrl_reg, ldb->ldb_ctrl);
 97}
 98
 99int ldb_bridge_attach_helper(struct drm_bridge *bridge,
100			     enum drm_bridge_attach_flags flags)
101{
102	struct ldb_channel *ldb_ch = bridge->driver_private;
103	struct ldb *ldb = ldb_ch->ldb;
104
105	if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) {
106		DRM_DEV_ERROR(ldb->dev,
107			      "do not support creating a drm_connector\n");
108		return -EINVAL;
109	}
110
111	if (!bridge->encoder) {
112		DRM_DEV_ERROR(ldb->dev, "missing encoder\n");
113		return -ENODEV;
114	}
115
116	return drm_bridge_attach(bridge->encoder,
117				ldb_ch->next_bridge, bridge,
118				DRM_BRIDGE_ATTACH_NO_CONNECTOR);
119}
120
121int ldb_init_helper(struct ldb *ldb)
122{
123	struct device *dev = ldb->dev;
124	struct device_node *np = dev->of_node;
125	struct device_node *child;
126	int ret;
127	u32 i;
128
129	ldb->regmap = syscon_node_to_regmap(np->parent);
130	if (IS_ERR(ldb->regmap)) {
131		ret = PTR_ERR(ldb->regmap);
132		if (ret != -EPROBE_DEFER)
133			DRM_DEV_ERROR(dev, "failed to get regmap: %d\n", ret);
134		return ret;
135	}
136
137	for_each_available_child_of_node(np, child) {
138		struct ldb_channel *ldb_ch;
139
140		ret = of_property_read_u32(child, "reg", &i);
141		if (ret || i > MAX_LDB_CHAN_NUM - 1) {
142			ret = -EINVAL;
143			DRM_DEV_ERROR(dev,
144				      "invalid channel node address: %u\n", i);
145			of_node_put(child);
146			return ret;
147		}
148
149		ldb_ch = ldb->channel[i];
150		ldb_ch->ldb = ldb;
151		ldb_ch->chno = i;
152		ldb_ch->is_available = true;
153		ldb_ch->np = child;
154
155		ldb->available_ch_cnt++;
156	}
157
158	return 0;
159}
160
161int ldb_find_next_bridge_helper(struct ldb *ldb)
162{
163	struct device *dev = ldb->dev;
164	struct ldb_channel *ldb_ch;
165	int ret, i;
166
167	for (i = 0; i < MAX_LDB_CHAN_NUM; i++) {
168		ldb_ch = ldb->channel[i];
169
170		if (!ldb_ch->is_available)
171			continue;
172
173		ldb_ch->next_bridge = devm_drm_of_get_bridge(dev, ldb_ch->np,
174							     1, 0);
175		if (IS_ERR(ldb_ch->next_bridge)) {
176			ret = PTR_ERR(ldb_ch->next_bridge);
177			if (ret != -EPROBE_DEFER)
178				DRM_DEV_ERROR(dev,
179					      "failed to get next bridge: %d\n",
180					      ret);
181			return ret;
182		}
183	}
184
185	return 0;
186}
187
188void ldb_add_bridge_helper(struct ldb *ldb,
189			   const struct drm_bridge_funcs *bridge_funcs)
190{
191	struct ldb_channel *ldb_ch;
192	int i;
193
194	for (i = 0; i < MAX_LDB_CHAN_NUM; i++) {
195		ldb_ch = ldb->channel[i];
196
197		if (!ldb_ch->is_available)
198			continue;
199
200		ldb_ch->bridge.driver_private = ldb_ch;
201		ldb_ch->bridge.funcs = bridge_funcs;
202		ldb_ch->bridge.of_node = ldb_ch->np;
203
204		drm_bridge_add(&ldb_ch->bridge);
205	}
206}
207
208void ldb_remove_bridge_helper(struct ldb *ldb)
209{
210	struct ldb_channel *ldb_ch;
211	int i;
212
213	for (i = 0; i < MAX_LDB_CHAN_NUM; i++) {
214		ldb_ch = ldb->channel[i];
215
216		if (!ldb_ch->is_available)
217			continue;
218
219		drm_bridge_remove(&ldb_ch->bridge);
220	}
221}