1 /* 2 * Copyright (C) 2016 Broadcom Limited 3 * 4 * This program is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License version 2 as published by 6 * the Free Software Foundation. 7 * 8 * This program is distributed in the hope that it will be useful, but WITHOUT 9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 * more details. 12 * 13 * You should have received a copy of the GNU General Public License along with 14 * this program. If not, see <http://www.gnu.org/licenses/>. 15 */ 16 17 /** 18 * DOC: VC4 DPI module 19 * 20 * The VC4 DPI hardware supports MIPI DPI type 4 and Nokia ViSSI 21 * signals. On BCM2835, these can be routed out to GPIO0-27 with the 22 * ALT2 function. 23 */ 24 25 #include <drm/drm_atomic_helper.h> 26 #include <drm/drm_bridge.h> 27 #include <drm/drm_crtc_helper.h> 28 #include <drm/drm_edid.h> 29 #include <drm/drm_of.h> 30 #include <drm/drm_panel.h> 31 #include <linux/clk.h> 32 #include <linux/component.h> 33 #include <linux/of_graph.h> 34 #include <linux/of_platform.h> 35 #include "vc4_drv.h" 36 #include "vc4_regs.h" 37 38 #define DPI_C 0x00 39 # define DPI_OUTPUT_ENABLE_MODE BIT(16) 40 41 /* The order field takes the incoming 24 bit RGB from the pixel valve 42 * and shuffles the 3 channels. 43 */ 44 # define DPI_ORDER_MASK VC4_MASK(15, 14) 45 # define DPI_ORDER_SHIFT 14 46 # define DPI_ORDER_RGB 0 47 # define DPI_ORDER_BGR 1 48 # define DPI_ORDER_GRB 2 49 # define DPI_ORDER_BRG 3 50 51 /* The format field takes the ORDER-shuffled pixel valve data and 52 * formats it onto the output lines. 53 */ 54 # define DPI_FORMAT_MASK VC4_MASK(13, 11) 55 # define DPI_FORMAT_SHIFT 11 56 /* This define is named in the hardware, but actually just outputs 0. */ 57 # define DPI_FORMAT_9BIT_666_RGB 0 58 /* Outputs 00000000rrrrrggggggbbbbb */ 59 # define DPI_FORMAT_16BIT_565_RGB_1 1 60 /* Outputs 000rrrrr00gggggg000bbbbb */ 61 # define DPI_FORMAT_16BIT_565_RGB_2 2 62 /* Outputs 00rrrrr000gggggg00bbbbb0 */ 63 # define DPI_FORMAT_16BIT_565_RGB_3 3 64 /* Outputs 000000rrrrrrggggggbbbbbb */ 65 # define DPI_FORMAT_18BIT_666_RGB_1 4 66 /* Outputs 00rrrrrr00gggggg00bbbbbb */ 67 # define DPI_FORMAT_18BIT_666_RGB_2 5 68 /* Outputs rrrrrrrrggggggggbbbbbbbb */ 69 # define DPI_FORMAT_24BIT_888_RGB 6 70 71 /* Reverses the polarity of the corresponding signal */ 72 # define DPI_PIXEL_CLK_INVERT BIT(10) 73 # define DPI_HSYNC_INVERT BIT(9) 74 # define DPI_VSYNC_INVERT BIT(8) 75 # define DPI_OUTPUT_ENABLE_INVERT BIT(7) 76 77 /* Outputs the signal the falling clock edge instead of rising. */ 78 # define DPI_HSYNC_NEGATE BIT(6) 79 # define DPI_VSYNC_NEGATE BIT(5) 80 # define DPI_OUTPUT_ENABLE_NEGATE BIT(4) 81 82 /* Disables the signal */ 83 # define DPI_HSYNC_DISABLE BIT(3) 84 # define DPI_VSYNC_DISABLE BIT(2) 85 # define DPI_OUTPUT_ENABLE_DISABLE BIT(1) 86 87 /* Power gate to the device, full reset at 0 -> 1 transition */ 88 # define DPI_ENABLE BIT(0) 89 90 /* All other registers besides DPI_C return the ID */ 91 #define DPI_ID 0x04 92 # define DPI_ID_VALUE 0x00647069 93 94 /* General DPI hardware state. */ 95 struct vc4_dpi { 96 struct platform_device *pdev; 97 98 struct drm_encoder *encoder; 99 struct drm_connector *connector; 100 struct drm_bridge *bridge; 101 bool is_panel_bridge; 102 103 void __iomem *regs; 104 105 struct clk *pixel_clock; 106 struct clk *core_clock; 107 }; 108 109 #define DPI_READ(offset) readl(dpi->regs + (offset)) 110 #define DPI_WRITE(offset, val) writel(val, dpi->regs + (offset)) 111 112 /* VC4 DPI encoder KMS struct */ 113 struct vc4_dpi_encoder { 114 struct vc4_encoder base; 115 struct vc4_dpi *dpi; 116 }; 117 118 static inline struct vc4_dpi_encoder * 119 to_vc4_dpi_encoder(struct drm_encoder *encoder) 120 { 121 return container_of(encoder, struct vc4_dpi_encoder, base.base); 122 } 123 124 #define DPI_REG(reg) { reg, #reg } 125 static const struct { 126 u32 reg; 127 const char *name; 128 } dpi_regs[] = { 129 DPI_REG(DPI_C), 130 DPI_REG(DPI_ID), 131 }; 132 133 #ifdef CONFIG_DEBUG_FS 134 int vc4_dpi_debugfs_regs(struct seq_file *m, void *unused) 135 { 136 struct drm_info_node *node = (struct drm_info_node *)m->private; 137 struct drm_device *dev = node->minor->dev; 138 struct vc4_dev *vc4 = to_vc4_dev(dev); 139 struct vc4_dpi *dpi = vc4->dpi; 140 int i; 141 142 if (!dpi) 143 return 0; 144 145 for (i = 0; i < ARRAY_SIZE(dpi_regs); i++) { 146 seq_printf(m, "%s (0x%04x): 0x%08x\n", 147 dpi_regs[i].name, dpi_regs[i].reg, 148 DPI_READ(dpi_regs[i].reg)); 149 } 150 151 return 0; 152 } 153 #endif 154 155 static const struct drm_encoder_funcs vc4_dpi_encoder_funcs = { 156 .destroy = drm_encoder_cleanup, 157 }; 158 159 static void vc4_dpi_encoder_disable(struct drm_encoder *encoder) 160 { 161 struct vc4_dpi_encoder *vc4_encoder = to_vc4_dpi_encoder(encoder); 162 struct vc4_dpi *dpi = vc4_encoder->dpi; 163 164 clk_disable_unprepare(dpi->pixel_clock); 165 } 166 167 static void vc4_dpi_encoder_enable(struct drm_encoder *encoder) 168 { 169 struct drm_display_mode *mode = &encoder->crtc->mode; 170 struct vc4_dpi_encoder *vc4_encoder = to_vc4_dpi_encoder(encoder); 171 struct vc4_dpi *dpi = vc4_encoder->dpi; 172 u32 dpi_c = DPI_ENABLE | DPI_OUTPUT_ENABLE_MODE; 173 int ret; 174 175 if (dpi->connector->display_info.num_bus_formats) { 176 u32 bus_format = dpi->connector->display_info.bus_formats[0]; 177 178 switch (bus_format) { 179 case MEDIA_BUS_FMT_RGB888_1X24: 180 dpi_c |= VC4_SET_FIELD(DPI_FORMAT_24BIT_888_RGB, 181 DPI_FORMAT); 182 break; 183 case MEDIA_BUS_FMT_BGR888_1X24: 184 dpi_c |= VC4_SET_FIELD(DPI_FORMAT_24BIT_888_RGB, 185 DPI_FORMAT); 186 dpi_c |= VC4_SET_FIELD(DPI_ORDER_BGR, DPI_ORDER); 187 break; 188 case MEDIA_BUS_FMT_RGB666_1X24_CPADHI: 189 dpi_c |= VC4_SET_FIELD(DPI_FORMAT_18BIT_666_RGB_2, 190 DPI_FORMAT); 191 break; 192 case MEDIA_BUS_FMT_RGB666_1X18: 193 dpi_c |= VC4_SET_FIELD(DPI_FORMAT_18BIT_666_RGB_1, 194 DPI_FORMAT); 195 break; 196 case MEDIA_BUS_FMT_RGB565_1X16: 197 dpi_c |= VC4_SET_FIELD(DPI_FORMAT_16BIT_565_RGB_3, 198 DPI_FORMAT); 199 break; 200 default: 201 DRM_ERROR("Unknown media bus format %d\n", bus_format); 202 break; 203 } 204 } 205 206 if (mode->flags & DRM_MODE_FLAG_NHSYNC) 207 dpi_c |= DPI_HSYNC_INVERT; 208 else if (!(mode->flags & DRM_MODE_FLAG_PHSYNC)) 209 dpi_c |= DPI_HSYNC_DISABLE; 210 211 if (mode->flags & DRM_MODE_FLAG_NVSYNC) 212 dpi_c |= DPI_VSYNC_INVERT; 213 else if (!(mode->flags & DRM_MODE_FLAG_PVSYNC)) 214 dpi_c |= DPI_VSYNC_DISABLE; 215 216 DPI_WRITE(DPI_C, dpi_c); 217 218 ret = clk_set_rate(dpi->pixel_clock, mode->clock * 1000); 219 if (ret) 220 DRM_ERROR("Failed to set clock rate: %d\n", ret); 221 222 ret = clk_prepare_enable(dpi->pixel_clock); 223 if (ret) 224 DRM_ERROR("Failed to set clock rate: %d\n", ret); 225 } 226 227 static bool vc4_dpi_encoder_mode_fixup(struct drm_encoder *encoder, 228 const struct drm_display_mode *mode, 229 struct drm_display_mode *adjusted_mode) 230 { 231 if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) 232 return false; 233 234 return true; 235 } 236 237 static const struct drm_encoder_helper_funcs vc4_dpi_encoder_helper_funcs = { 238 .disable = vc4_dpi_encoder_disable, 239 .enable = vc4_dpi_encoder_enable, 240 .mode_fixup = vc4_dpi_encoder_mode_fixup, 241 }; 242 243 static const struct of_device_id vc4_dpi_dt_match[] = { 244 { .compatible = "brcm,bcm2835-dpi", .data = NULL }, 245 {} 246 }; 247 248 /* Sets up the next link in the display chain, whether it's a panel or 249 * a bridge. 250 */ 251 static int vc4_dpi_init_bridge(struct vc4_dpi *dpi) 252 { 253 struct device *dev = &dpi->pdev->dev; 254 struct drm_panel *panel; 255 int ret; 256 257 ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0, 258 &panel, &dpi->bridge); 259 if (ret) { 260 /* If nothing was connected in the DT, that's not an 261 * error. 262 */ 263 if (ret == -ENODEV) 264 return 0; 265 else 266 return ret; 267 } 268 269 if (panel) { 270 dpi->bridge = drm_panel_bridge_add(panel, 271 DRM_MODE_CONNECTOR_DPI); 272 dpi->is_panel_bridge = true; 273 } 274 275 return drm_bridge_attach(dpi->encoder, dpi->bridge, NULL); 276 } 277 278 static int vc4_dpi_bind(struct device *dev, struct device *master, void *data) 279 { 280 struct platform_device *pdev = to_platform_device(dev); 281 struct drm_device *drm = dev_get_drvdata(master); 282 struct vc4_dev *vc4 = to_vc4_dev(drm); 283 struct vc4_dpi *dpi; 284 struct vc4_dpi_encoder *vc4_dpi_encoder; 285 int ret; 286 287 dpi = devm_kzalloc(dev, sizeof(*dpi), GFP_KERNEL); 288 if (!dpi) 289 return -ENOMEM; 290 291 vc4_dpi_encoder = devm_kzalloc(dev, sizeof(*vc4_dpi_encoder), 292 GFP_KERNEL); 293 if (!vc4_dpi_encoder) 294 return -ENOMEM; 295 vc4_dpi_encoder->base.type = VC4_ENCODER_TYPE_DPI; 296 vc4_dpi_encoder->dpi = dpi; 297 dpi->encoder = &vc4_dpi_encoder->base.base; 298 299 dpi->pdev = pdev; 300 dpi->regs = vc4_ioremap_regs(pdev, 0); 301 if (IS_ERR(dpi->regs)) 302 return PTR_ERR(dpi->regs); 303 304 if (DPI_READ(DPI_ID) != DPI_ID_VALUE) { 305 dev_err(dev, "Port returned 0x%08x for ID instead of 0x%08x\n", 306 DPI_READ(DPI_ID), DPI_ID_VALUE); 307 return -ENODEV; 308 } 309 310 dpi->core_clock = devm_clk_get(dev, "core"); 311 if (IS_ERR(dpi->core_clock)) { 312 ret = PTR_ERR(dpi->core_clock); 313 if (ret != -EPROBE_DEFER) 314 DRM_ERROR("Failed to get core clock: %d\n", ret); 315 return ret; 316 } 317 dpi->pixel_clock = devm_clk_get(dev, "pixel"); 318 if (IS_ERR(dpi->pixel_clock)) { 319 ret = PTR_ERR(dpi->pixel_clock); 320 if (ret != -EPROBE_DEFER) 321 DRM_ERROR("Failed to get pixel clock: %d\n", ret); 322 return ret; 323 } 324 325 ret = clk_prepare_enable(dpi->core_clock); 326 if (ret) 327 DRM_ERROR("Failed to turn on core clock: %d\n", ret); 328 329 drm_encoder_init(drm, dpi->encoder, &vc4_dpi_encoder_funcs, 330 DRM_MODE_ENCODER_DPI, NULL); 331 drm_encoder_helper_add(dpi->encoder, &vc4_dpi_encoder_helper_funcs); 332 333 ret = vc4_dpi_init_bridge(dpi); 334 if (ret) 335 goto err_destroy_encoder; 336 337 dev_set_drvdata(dev, dpi); 338 339 vc4->dpi = dpi; 340 341 return 0; 342 343 err_destroy_encoder: 344 drm_encoder_cleanup(dpi->encoder); 345 clk_disable_unprepare(dpi->core_clock); 346 return ret; 347 } 348 349 static void vc4_dpi_unbind(struct device *dev, struct device *master, 350 void *data) 351 { 352 struct drm_device *drm = dev_get_drvdata(master); 353 struct vc4_dev *vc4 = to_vc4_dev(drm); 354 struct vc4_dpi *dpi = dev_get_drvdata(dev); 355 356 if (dpi->is_panel_bridge) 357 drm_panel_bridge_remove(dpi->bridge); 358 359 drm_encoder_cleanup(dpi->encoder); 360 361 clk_disable_unprepare(dpi->core_clock); 362 363 vc4->dpi = NULL; 364 } 365 366 static const struct component_ops vc4_dpi_ops = { 367 .bind = vc4_dpi_bind, 368 .unbind = vc4_dpi_unbind, 369 }; 370 371 static int vc4_dpi_dev_probe(struct platform_device *pdev) 372 { 373 return component_add(&pdev->dev, &vc4_dpi_ops); 374 } 375 376 static int vc4_dpi_dev_remove(struct platform_device *pdev) 377 { 378 component_del(&pdev->dev, &vc4_dpi_ops); 379 return 0; 380 } 381 382 struct platform_driver vc4_dpi_driver = { 383 .probe = vc4_dpi_dev_probe, 384 .remove = vc4_dpi_dev_remove, 385 .driver = { 386 .name = "vc4_dpi", 387 .of_match_table = vc4_dpi_dt_match, 388 }, 389 }; 390