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 v5.1-rc6 243 lines 5.7 kB view raw
1/* 2 * Copyright (C) 2012-2016 Mentor Graphics Inc. 3 * Copyright (C) 2005-2009 Freescale Semiconductor, Inc. 4 * 5 * This program is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License as published by the 7 * Free Software Foundation; either version 2 of the License, or (at your 8 * option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, but 11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * for more details. 14 */ 15#include <linux/io.h> 16#include "ipu-prv.h" 17 18struct ipu_vdi { 19 void __iomem *base; 20 u32 module; 21 spinlock_t lock; 22 int use_count; 23 struct ipu_soc *ipu; 24}; 25 26 27/* VDI Register Offsets */ 28#define VDI_FSIZE 0x0000 29#define VDI_C 0x0004 30 31/* VDI Register Fields */ 32#define VDI_C_CH_420 (0 << 1) 33#define VDI_C_CH_422 (1 << 1) 34#define VDI_C_MOT_SEL_MASK (0x3 << 2) 35#define VDI_C_MOT_SEL_FULL (2 << 2) 36#define VDI_C_MOT_SEL_LOW (1 << 2) 37#define VDI_C_MOT_SEL_MED (0 << 2) 38#define VDI_C_BURST_SIZE1_4 (3 << 4) 39#define VDI_C_BURST_SIZE2_4 (3 << 8) 40#define VDI_C_BURST_SIZE3_4 (3 << 12) 41#define VDI_C_BURST_SIZE_MASK 0xF 42#define VDI_C_BURST_SIZE1_OFFSET 4 43#define VDI_C_BURST_SIZE2_OFFSET 8 44#define VDI_C_BURST_SIZE3_OFFSET 12 45#define VDI_C_VWM1_SET_1 (0 << 16) 46#define VDI_C_VWM1_SET_2 (1 << 16) 47#define VDI_C_VWM1_CLR_2 (1 << 19) 48#define VDI_C_VWM3_SET_1 (0 << 22) 49#define VDI_C_VWM3_SET_2 (1 << 22) 50#define VDI_C_VWM3_CLR_2 (1 << 25) 51#define VDI_C_TOP_FIELD_MAN_1 (1 << 30) 52#define VDI_C_TOP_FIELD_AUTO_1 (1 << 31) 53 54static inline u32 ipu_vdi_read(struct ipu_vdi *vdi, unsigned int offset) 55{ 56 return readl(vdi->base + offset); 57} 58 59static inline void ipu_vdi_write(struct ipu_vdi *vdi, u32 value, 60 unsigned int offset) 61{ 62 writel(value, vdi->base + offset); 63} 64 65void ipu_vdi_set_field_order(struct ipu_vdi *vdi, v4l2_std_id std, u32 field) 66{ 67 bool top_field_0 = false; 68 unsigned long flags; 69 u32 reg; 70 71 switch (field) { 72 case V4L2_FIELD_INTERLACED_TB: 73 case V4L2_FIELD_SEQ_TB: 74 case V4L2_FIELD_TOP: 75 top_field_0 = true; 76 break; 77 case V4L2_FIELD_INTERLACED_BT: 78 case V4L2_FIELD_SEQ_BT: 79 case V4L2_FIELD_BOTTOM: 80 top_field_0 = false; 81 break; 82 default: 83 top_field_0 = (std & V4L2_STD_525_60) ? true : false; 84 break; 85 } 86 87 spin_lock_irqsave(&vdi->lock, flags); 88 89 reg = ipu_vdi_read(vdi, VDI_C); 90 if (top_field_0) 91 reg &= ~(VDI_C_TOP_FIELD_MAN_1 | VDI_C_TOP_FIELD_AUTO_1); 92 else 93 reg |= VDI_C_TOP_FIELD_MAN_1 | VDI_C_TOP_FIELD_AUTO_1; 94 ipu_vdi_write(vdi, reg, VDI_C); 95 96 spin_unlock_irqrestore(&vdi->lock, flags); 97} 98EXPORT_SYMBOL_GPL(ipu_vdi_set_field_order); 99 100void ipu_vdi_set_motion(struct ipu_vdi *vdi, enum ipu_motion_sel motion_sel) 101{ 102 unsigned long flags; 103 u32 reg; 104 105 spin_lock_irqsave(&vdi->lock, flags); 106 107 reg = ipu_vdi_read(vdi, VDI_C); 108 109 reg &= ~VDI_C_MOT_SEL_MASK; 110 111 switch (motion_sel) { 112 case MED_MOTION: 113 reg |= VDI_C_MOT_SEL_MED; 114 break; 115 case HIGH_MOTION: 116 reg |= VDI_C_MOT_SEL_FULL; 117 break; 118 default: 119 reg |= VDI_C_MOT_SEL_LOW; 120 break; 121 } 122 123 ipu_vdi_write(vdi, reg, VDI_C); 124 125 spin_unlock_irqrestore(&vdi->lock, flags); 126} 127EXPORT_SYMBOL_GPL(ipu_vdi_set_motion); 128 129void ipu_vdi_setup(struct ipu_vdi *vdi, u32 code, int xres, int yres) 130{ 131 unsigned long flags; 132 u32 pixel_fmt, reg; 133 134 spin_lock_irqsave(&vdi->lock, flags); 135 136 reg = ((yres - 1) << 16) | (xres - 1); 137 ipu_vdi_write(vdi, reg, VDI_FSIZE); 138 139 /* 140 * Full motion, only vertical filter is used. 141 * Burst size is 4 accesses 142 */ 143 if (code == MEDIA_BUS_FMT_UYVY8_2X8 || 144 code == MEDIA_BUS_FMT_UYVY8_1X16 || 145 code == MEDIA_BUS_FMT_YUYV8_2X8 || 146 code == MEDIA_BUS_FMT_YUYV8_1X16) 147 pixel_fmt = VDI_C_CH_422; 148 else 149 pixel_fmt = VDI_C_CH_420; 150 151 reg = ipu_vdi_read(vdi, VDI_C); 152 reg |= pixel_fmt; 153 reg |= VDI_C_BURST_SIZE2_4; 154 reg |= VDI_C_BURST_SIZE1_4 | VDI_C_VWM1_CLR_2; 155 reg |= VDI_C_BURST_SIZE3_4 | VDI_C_VWM3_CLR_2; 156 ipu_vdi_write(vdi, reg, VDI_C); 157 158 spin_unlock_irqrestore(&vdi->lock, flags); 159} 160EXPORT_SYMBOL_GPL(ipu_vdi_setup); 161 162void ipu_vdi_unsetup(struct ipu_vdi *vdi) 163{ 164 unsigned long flags; 165 166 spin_lock_irqsave(&vdi->lock, flags); 167 ipu_vdi_write(vdi, 0, VDI_FSIZE); 168 ipu_vdi_write(vdi, 0, VDI_C); 169 spin_unlock_irqrestore(&vdi->lock, flags); 170} 171EXPORT_SYMBOL_GPL(ipu_vdi_unsetup); 172 173int ipu_vdi_enable(struct ipu_vdi *vdi) 174{ 175 unsigned long flags; 176 177 spin_lock_irqsave(&vdi->lock, flags); 178 179 if (!vdi->use_count) 180 ipu_module_enable(vdi->ipu, vdi->module); 181 182 vdi->use_count++; 183 184 spin_unlock_irqrestore(&vdi->lock, flags); 185 186 return 0; 187} 188EXPORT_SYMBOL_GPL(ipu_vdi_enable); 189 190int ipu_vdi_disable(struct ipu_vdi *vdi) 191{ 192 unsigned long flags; 193 194 spin_lock_irqsave(&vdi->lock, flags); 195 196 if (vdi->use_count) { 197 if (!--vdi->use_count) 198 ipu_module_disable(vdi->ipu, vdi->module); 199 } 200 201 spin_unlock_irqrestore(&vdi->lock, flags); 202 203 return 0; 204} 205EXPORT_SYMBOL_GPL(ipu_vdi_disable); 206 207struct ipu_vdi *ipu_vdi_get(struct ipu_soc *ipu) 208{ 209 return ipu->vdi_priv; 210} 211EXPORT_SYMBOL_GPL(ipu_vdi_get); 212 213void ipu_vdi_put(struct ipu_vdi *vdi) 214{ 215} 216EXPORT_SYMBOL_GPL(ipu_vdi_put); 217 218int ipu_vdi_init(struct ipu_soc *ipu, struct device *dev, 219 unsigned long base, u32 module) 220{ 221 struct ipu_vdi *vdi; 222 223 vdi = devm_kzalloc(dev, sizeof(*vdi), GFP_KERNEL); 224 if (!vdi) 225 return -ENOMEM; 226 227 ipu->vdi_priv = vdi; 228 229 spin_lock_init(&vdi->lock); 230 vdi->module = module; 231 vdi->base = devm_ioremap(dev, base, PAGE_SIZE); 232 if (!vdi->base) 233 return -ENOMEM; 234 235 dev_dbg(dev, "VDI base: 0x%08lx remapped to %p\n", base, vdi->base); 236 vdi->ipu = ipu; 237 238 return 0; 239} 240 241void ipu_vdi_exit(struct ipu_soc *ipu) 242{ 243}