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