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 18 bool ldb_channel_is_single_link(struct ldb_channel *ldb_ch) 19 { 20 return ldb_ch->link_type == LDB_CH_SINGLE_LINK; 21 } 22 23 bool 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 29 int 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 42 void 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 73 void 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 85 void 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 99 int 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 121 int 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 161 int 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 188 void 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 208 void 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 } 222