1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (c) 2017 Theobroma Systems Design und Consulting GmbH 4 * Copyright (c) 2015 Google, Inc 5 * Copyright 2014 Rockchip Inc. 6 */ 7 8 #include <common.h> 9 #include <display.h> 10 #include <dm.h> 11 #include <regmap.h> 12 #include <syscon.h> 13 #include <video.h> 14 #include <asm/hardware.h> 15 #include <asm/io.h> 16 #include <asm/arch/clock.h> 17 #include <asm/arch/grf_rk3288.h> 18 #include "rk_vop.h" 19 20 DECLARE_GLOBAL_DATA_PTR; 21 22 static void rk3288_set_pin_polarity(struct udevice *dev, 23 enum vop_modes mode, u32 polarity) 24 { 25 struct rk_vop_priv *priv = dev_get_priv(dev); 26 struct rk3288_vop *regs = priv->regs; 27 28 /* The RK3328 VOP (v3.1) has its polarity configuration in ctrl0 */ 29 clrsetbits_le32(®s->dsp_ctrl0, 30 M_DSP_DCLK_POL | M_DSP_DEN_POL | 31 M_DSP_VSYNC_POL | M_DSP_HSYNC_POL, 32 V_DSP_PIN_POL(polarity)); 33 } 34 35 static void rk3288_set_io_vsel(struct udevice *dev) 36 { 37 struct rk3288_grf *grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); 38 39 /* lcdc(vop) iodomain select 1.8V */ 40 rk_setreg(&grf->io_vsel, 1 << 0); 41 } 42 43 /* 44 * Try some common regulators. We should really get these from the 45 * device tree somehow. 46 */ 47 static const char * const rk3288_regulator_names[] = { 48 "vcc18_lcd", 49 "VCC18_LCD", 50 "vdd10_lcd_pwren_h", 51 "vdd10_lcd", 52 "VDD10_LCD", 53 "vcc33_lcd" 54 }; 55 56 static int rk3288_vop_probe(struct udevice *dev) 57 { 58 /* Before relocation we don't need to do anything */ 59 if (!(gd->flags & GD_FLG_RELOC)) 60 return 0; 61 62 /* Set the LCDC(vop) iodomain to 1.8V */ 63 rk3288_set_io_vsel(dev); 64 65 /* Probe regulators required for the RK3288 VOP */ 66 rk_vop_probe_regulators(dev, rk3288_regulator_names, 67 ARRAY_SIZE(rk3288_regulator_names)); 68 69 return rk_vop_probe(dev); 70 } 71 72 static int rk_vop_remove(struct udevice *dev) 73 { 74 struct rk_vop_priv *priv = dev_get_priv(dev); 75 struct rk3288_vop *regs = priv->regs; 76 77 setbits_le32(®s->sys_ctrl, V_STANDBY_EN(1)); 78 79 /* wait frame complete (60Hz) to enter standby */ 80 mdelay(17); 81 82 return 0; 83 } 84 85 struct rkvop_driverdata rk3288_driverdata = { 86 .features = VOP_FEATURE_OUTPUT_10BIT, 87 .set_pin_polarity = rk3288_set_pin_polarity, 88 }; 89 90 static const struct udevice_id rk3288_vop_ids[] = { 91 { .compatible = "rockchip,rk3288-vop", 92 .data = (ulong)&rk3288_driverdata }, 93 { } 94 }; 95 96 static const struct video_ops rk3288_vop_ops = { 97 }; 98 99 U_BOOT_DRIVER(rk_vop) = { 100 .name = "rk3288_vop", 101 .id = UCLASS_VIDEO, 102 .of_match = rk3288_vop_ids, 103 .ops = &rk3288_vop_ops, 104 .bind = rk_vop_bind, 105 .probe = rk3288_vop_probe, 106 .remove = rk_vop_remove, 107 .priv_auto_alloc_size = sizeof(struct rk_vop_priv), 108 }; 109