Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.14 265 lines 8.0 kB view raw
1/* 2 * rcar_du_group.c -- R-Car Display Unit Channels Pair 3 * 4 * Copyright (C) 2013-2015 Renesas Electronics Corporation 5 * 6 * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 */ 13 14/* 15 * The R8A7779 DU is split in per-CRTC resources (scan-out engine, blending 16 * unit, timings generator, ...) and device-global resources (start/stop 17 * control, planes, ...) shared between the two CRTCs. 18 * 19 * The R8A7790 introduced a third CRTC with its own set of global resources. 20 * This would be modeled as two separate DU device instances if it wasn't for 21 * a handful or resources that are shared between the three CRTCs (mostly 22 * related to input and output routing). For this reason the R8A7790 DU must be 23 * modeled as a single device with three CRTCs, two sets of "semi-global" 24 * resources, and a few device-global resources. 25 * 26 * The rcar_du_group object is a driver specific object, without any real 27 * counterpart in the DU documentation, that models those semi-global resources. 28 */ 29 30#include <linux/clk.h> 31#include <linux/io.h> 32 33#include "rcar_du_drv.h" 34#include "rcar_du_group.h" 35#include "rcar_du_regs.h" 36 37u32 rcar_du_group_read(struct rcar_du_group *rgrp, u32 reg) 38{ 39 return rcar_du_read(rgrp->dev, rgrp->mmio_offset + reg); 40} 41 42void rcar_du_group_write(struct rcar_du_group *rgrp, u32 reg, u32 data) 43{ 44 rcar_du_write(rgrp->dev, rgrp->mmio_offset + reg, data); 45} 46 47static void rcar_du_group_setup_pins(struct rcar_du_group *rgrp) 48{ 49 u32 defr6 = DEFR6_CODE | DEFR6_ODPM12_DISP; 50 51 if (rgrp->num_crtcs > 1) 52 defr6 |= DEFR6_ODPM22_DISP; 53 54 rcar_du_group_write(rgrp, DEFR6, defr6); 55} 56 57static void rcar_du_group_setup_defr8(struct rcar_du_group *rgrp) 58{ 59 struct rcar_du_device *rcdu = rgrp->dev; 60 unsigned int possible_crtcs = 61 rcdu->info->routes[RCAR_DU_OUTPUT_DPAD0].possible_crtcs; 62 u32 defr8 = DEFR8_CODE; 63 64 if (rcdu->info->gen < 3) { 65 defr8 |= DEFR8_DEFE8; 66 67 /* 68 * On Gen2 the DEFR8 register for the first group also controls 69 * RGB output routing to DPAD0 and VSPD1 routing to DU0/1/2 for 70 * DU instances that support it. 71 */ 72 if (rgrp->index == 0) { 73 if (possible_crtcs > 1) 74 defr8 |= DEFR8_DRGBS_DU(rcdu->dpad0_source); 75 if (rgrp->dev->vspd1_sink == 2) 76 defr8 |= DEFR8_VSCS; 77 } 78 } else { 79 /* 80 * On Gen3 VSPD routing can't be configured, but DPAD routing 81 * needs to be set despite having a single option available. 82 */ 83 u32 crtc = ffs(possible_crtcs) - 1; 84 85 if (crtc / 2 == rgrp->index) 86 defr8 |= DEFR8_DRGBS_DU(crtc); 87 } 88 89 rcar_du_group_write(rgrp, DEFR8, defr8); 90} 91 92static void rcar_du_group_setup(struct rcar_du_group *rgrp) 93{ 94 struct rcar_du_device *rcdu = rgrp->dev; 95 96 /* Enable extended features */ 97 rcar_du_group_write(rgrp, DEFR, DEFR_CODE | DEFR_DEFE); 98 if (rcdu->info->gen < 3) { 99 rcar_du_group_write(rgrp, DEFR2, DEFR2_CODE | DEFR2_DEFE2G); 100 rcar_du_group_write(rgrp, DEFR3, DEFR3_CODE | DEFR3_DEFE3); 101 rcar_du_group_write(rgrp, DEFR4, DEFR4_CODE); 102 } 103 rcar_du_group_write(rgrp, DEFR5, DEFR5_CODE | DEFR5_DEFE5); 104 105 rcar_du_group_setup_pins(rgrp); 106 107 if (rcar_du_has(rgrp->dev, RCAR_DU_FEATURE_EXT_CTRL_REGS)) { 108 rcar_du_group_setup_defr8(rgrp); 109 110 /* 111 * Configure input dot clock routing. We currently hardcode the 112 * configuration to routing DOTCLKINn to DUn. Register fields 113 * depend on the DU generation, but the resulting value is 0 in 114 * all cases. 115 * 116 * On Gen2 a single register in the first group controls dot 117 * clock selection for all channels, while on Gen3 dot clocks 118 * are setup through per-group registers, only available when 119 * the group has two channels. 120 */ 121 if ((rcdu->info->gen < 3 && rgrp->index == 0) || 122 (rcdu->info->gen == 3 && rgrp->num_crtcs > 1)) 123 rcar_du_group_write(rgrp, DIDSR, DIDSR_CODE); 124 } 125 126 if (rcdu->info->gen >= 3) 127 rcar_du_group_write(rgrp, DEFR10, DEFR10_CODE | DEFR10_DEFE10); 128 129 /* 130 * Use DS1PR and DS2PR to configure planes priorities and connects the 131 * superposition 0 to DU0 pins. DU1 pins will be configured dynamically. 132 */ 133 rcar_du_group_write(rgrp, DORCR, DORCR_PG1D_DS1 | DORCR_DPRS); 134 135 /* Apply planes to CRTCs association. */ 136 mutex_lock(&rgrp->lock); 137 rcar_du_group_write(rgrp, DPTSR, (rgrp->dptsr_planes << 16) | 138 rgrp->dptsr_planes); 139 mutex_unlock(&rgrp->lock); 140} 141 142/* 143 * rcar_du_group_get - Acquire a reference to the DU channels group 144 * 145 * Acquiring the first reference setups core registers. A reference must be held 146 * before accessing any hardware registers. 147 * 148 * This function must be called with the DRM mode_config lock held. 149 * 150 * Return 0 in case of success or a negative error code otherwise. 151 */ 152int rcar_du_group_get(struct rcar_du_group *rgrp) 153{ 154 if (rgrp->use_count) 155 goto done; 156 157 rcar_du_group_setup(rgrp); 158 159done: 160 rgrp->use_count++; 161 return 0; 162} 163 164/* 165 * rcar_du_group_put - Release a reference to the DU 166 * 167 * This function must be called with the DRM mode_config lock held. 168 */ 169void rcar_du_group_put(struct rcar_du_group *rgrp) 170{ 171 --rgrp->use_count; 172} 173 174static void __rcar_du_group_start_stop(struct rcar_du_group *rgrp, bool start) 175{ 176 rcar_du_group_write(rgrp, DSYSR, 177 (rcar_du_group_read(rgrp, DSYSR) & ~(DSYSR_DRES | DSYSR_DEN)) | 178 (start ? DSYSR_DEN : DSYSR_DRES)); 179} 180 181void rcar_du_group_start_stop(struct rcar_du_group *rgrp, bool start) 182{ 183 /* 184 * Many of the configuration bits are only updated when the display 185 * reset (DRES) bit in DSYSR is set to 1, disabling *both* CRTCs. Some 186 * of those bits could be pre-configured, but others (especially the 187 * bits related to plane assignment to display timing controllers) need 188 * to be modified at runtime. 189 * 190 * Restart the display controller if a start is requested. Sorry for the 191 * flicker. It should be possible to move most of the "DRES-update" bits 192 * setup to driver initialization time and minimize the number of cases 193 * when the display controller will have to be restarted. 194 */ 195 if (start) { 196 if (rgrp->used_crtcs++ != 0) 197 __rcar_du_group_start_stop(rgrp, false); 198 __rcar_du_group_start_stop(rgrp, true); 199 } else { 200 if (--rgrp->used_crtcs == 0) 201 __rcar_du_group_start_stop(rgrp, false); 202 } 203} 204 205void rcar_du_group_restart(struct rcar_du_group *rgrp) 206{ 207 rgrp->need_restart = false; 208 209 __rcar_du_group_start_stop(rgrp, false); 210 __rcar_du_group_start_stop(rgrp, true); 211} 212 213int rcar_du_set_dpad0_vsp1_routing(struct rcar_du_device *rcdu) 214{ 215 struct rcar_du_group *rgrp; 216 struct rcar_du_crtc *crtc; 217 unsigned int index; 218 int ret; 219 220 if (!rcar_du_has(rcdu, RCAR_DU_FEATURE_EXT_CTRL_REGS)) 221 return 0; 222 223 /* 224 * RGB output routing to DPAD0 and VSP1D routing to DU0/1/2 are 225 * configured in the DEFR8 register of the first group on Gen2 and the 226 * last group on Gen3. As this function can be called with the DU 227 * channels of the corresponding CRTCs disabled, we need to enable the 228 * group clock before accessing the register. 229 */ 230 index = rcdu->info->gen < 3 ? 0 : DIV_ROUND_UP(rcdu->num_crtcs, 2) - 1; 231 rgrp = &rcdu->groups[index]; 232 crtc = &rcdu->crtcs[index * 2]; 233 234 ret = clk_prepare_enable(crtc->clock); 235 if (ret < 0) 236 return ret; 237 238 rcar_du_group_setup_defr8(rgrp); 239 240 clk_disable_unprepare(crtc->clock); 241 242 return 0; 243} 244 245int rcar_du_group_set_routing(struct rcar_du_group *rgrp) 246{ 247 struct rcar_du_crtc *crtc0 = &rgrp->dev->crtcs[rgrp->index * 2]; 248 u32 dorcr = rcar_du_group_read(rgrp, DORCR); 249 250 dorcr &= ~(DORCR_PG2T | DORCR_DK2S | DORCR_PG2D_MASK); 251 252 /* 253 * Set the DPAD1 pins sources. Select CRTC 0 if explicitly requested and 254 * CRTC 1 in all other cases to avoid cloning CRTC 0 to DPAD0 and DPAD1 255 * by default. 256 */ 257 if (crtc0->outputs & BIT(RCAR_DU_OUTPUT_DPAD1)) 258 dorcr |= DORCR_PG2D_DS1; 259 else 260 dorcr |= DORCR_PG2T | DORCR_DK2S | DORCR_PG2D_DS2; 261 262 rcar_du_group_write(rgrp, DORCR, dorcr); 263 264 return rcar_du_set_dpad0_vsp1_routing(rgrp->dev); 265}