1 // SPDX-License-Identifier: GPL-2.0-only 2 /* linux/drivers/media/platform/samsung/s5p-jpeg/jpeg-hw.h 3 * 4 * Copyright (c) 2011 Samsung Electronics Co., Ltd. 5 * http://www.samsung.com 6 * 7 * Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com> 8 */ 9 10 #include <linux/io.h> 11 #include <linux/videodev2.h> 12 13 #include "jpeg-core.h" 14 #include "jpeg-regs.h" 15 #include "jpeg-hw-s5p.h" 16 17 void s5p_jpeg_reset(void __iomem *regs) 18 { 19 unsigned long reg; 20 21 writel(1, regs + S5P_JPG_SW_RESET); 22 reg = readl(regs + S5P_JPG_SW_RESET); 23 /* no other way but polling for when JPEG IP becomes operational */ 24 while (reg != 0) { 25 cpu_relax(); 26 reg = readl(regs + S5P_JPG_SW_RESET); 27 } 28 } 29 30 void s5p_jpeg_poweron(void __iomem *regs) 31 { 32 writel(S5P_POWER_ON, regs + S5P_JPGCLKCON); 33 } 34 35 void s5p_jpeg_input_raw_mode(void __iomem *regs, unsigned long mode) 36 { 37 unsigned long reg, m; 38 39 m = S5P_MOD_SEL_565; 40 if (mode == S5P_JPEG_RAW_IN_565) 41 m = S5P_MOD_SEL_565; 42 else if (mode == S5P_JPEG_RAW_IN_422) 43 m = S5P_MOD_SEL_422; 44 45 reg = readl(regs + S5P_JPGCMOD); 46 reg &= ~S5P_MOD_SEL_MASK; 47 reg |= m; 48 writel(reg, regs + S5P_JPGCMOD); 49 } 50 51 void s5p_jpeg_proc_mode(void __iomem *regs, unsigned long mode) 52 { 53 unsigned long reg, m; 54 55 if (mode == S5P_JPEG_ENCODE) 56 m = S5P_PROC_MODE_COMPR; 57 else 58 m = S5P_PROC_MODE_DECOMPR; 59 reg = readl(regs + S5P_JPGMOD); 60 reg &= ~S5P_PROC_MODE_MASK; 61 reg |= m; 62 writel(reg, regs + S5P_JPGMOD); 63 } 64 65 void s5p_jpeg_subsampling_mode(void __iomem *regs, unsigned int mode) 66 { 67 unsigned long reg, m; 68 69 if (mode == V4L2_JPEG_CHROMA_SUBSAMPLING_420) 70 m = S5P_SUBSAMPLING_MODE_420; 71 else 72 m = S5P_SUBSAMPLING_MODE_422; 73 74 reg = readl(regs + S5P_JPGMOD); 75 reg &= ~S5P_SUBSAMPLING_MODE_MASK; 76 reg |= m; 77 writel(reg, regs + S5P_JPGMOD); 78 } 79 80 unsigned int s5p_jpeg_get_subsampling_mode(void __iomem *regs) 81 { 82 return readl(regs + S5P_JPGMOD) & S5P_SUBSAMPLING_MODE_MASK; 83 } 84 85 void s5p_jpeg_dri(void __iomem *regs, unsigned int dri) 86 { 87 unsigned long reg; 88 89 reg = readl(regs + S5P_JPGDRI_U); 90 reg &= ~0xff; 91 reg |= (dri >> 8) & 0xff; 92 writel(reg, regs + S5P_JPGDRI_U); 93 94 reg = readl(regs + S5P_JPGDRI_L); 95 reg &= ~0xff; 96 reg |= dri & 0xff; 97 writel(reg, regs + S5P_JPGDRI_L); 98 } 99 100 void s5p_jpeg_qtbl(void __iomem *regs, unsigned int t, unsigned int n) 101 { 102 unsigned long reg; 103 104 reg = readl(regs + S5P_JPG_QTBL); 105 reg &= ~S5P_QT_NUMt_MASK(t); 106 reg |= (n << S5P_QT_NUMt_SHIFT(t)) & S5P_QT_NUMt_MASK(t); 107 writel(reg, regs + S5P_JPG_QTBL); 108 } 109 110 void s5p_jpeg_htbl_ac(void __iomem *regs, unsigned int t) 111 { 112 unsigned long reg; 113 114 reg = readl(regs + S5P_JPG_HTBL); 115 reg &= ~S5P_HT_NUMt_AC_MASK(t); 116 /* this driver uses table 0 for all color components */ 117 reg |= (0 << S5P_HT_NUMt_AC_SHIFT(t)) & S5P_HT_NUMt_AC_MASK(t); 118 writel(reg, regs + S5P_JPG_HTBL); 119 } 120 121 void s5p_jpeg_htbl_dc(void __iomem *regs, unsigned int t) 122 { 123 unsigned long reg; 124 125 reg = readl(regs + S5P_JPG_HTBL); 126 reg &= ~S5P_HT_NUMt_DC_MASK(t); 127 /* this driver uses table 0 for all color components */ 128 reg |= (0 << S5P_HT_NUMt_DC_SHIFT(t)) & S5P_HT_NUMt_DC_MASK(t); 129 writel(reg, regs + S5P_JPG_HTBL); 130 } 131 132 void s5p_jpeg_y(void __iomem *regs, unsigned int y) 133 { 134 unsigned long reg; 135 136 reg = readl(regs + S5P_JPGY_U); 137 reg &= ~0xff; 138 reg |= (y >> 8) & 0xff; 139 writel(reg, regs + S5P_JPGY_U); 140 141 reg = readl(regs + S5P_JPGY_L); 142 reg &= ~0xff; 143 reg |= y & 0xff; 144 writel(reg, regs + S5P_JPGY_L); 145 } 146 147 void s5p_jpeg_x(void __iomem *regs, unsigned int x) 148 { 149 unsigned long reg; 150 151 reg = readl(regs + S5P_JPGX_U); 152 reg &= ~0xff; 153 reg |= (x >> 8) & 0xff; 154 writel(reg, regs + S5P_JPGX_U); 155 156 reg = readl(regs + S5P_JPGX_L); 157 reg &= ~0xff; 158 reg |= x & 0xff; 159 writel(reg, regs + S5P_JPGX_L); 160 } 161 162 void s5p_jpeg_rst_int_enable(void __iomem *regs, bool enable) 163 { 164 unsigned long reg; 165 166 reg = readl(regs + S5P_JPGINTSE); 167 reg &= ~S5P_RSTm_INT_EN_MASK; 168 if (enable) 169 reg |= S5P_RSTm_INT_EN; 170 writel(reg, regs + S5P_JPGINTSE); 171 } 172 173 void s5p_jpeg_data_num_int_enable(void __iomem *regs, bool enable) 174 { 175 unsigned long reg; 176 177 reg = readl(regs + S5P_JPGINTSE); 178 reg &= ~S5P_DATA_NUM_INT_EN_MASK; 179 if (enable) 180 reg |= S5P_DATA_NUM_INT_EN; 181 writel(reg, regs + S5P_JPGINTSE); 182 } 183 184 void s5p_jpeg_final_mcu_num_int_enable(void __iomem *regs, bool enbl) 185 { 186 unsigned long reg; 187 188 reg = readl(regs + S5P_JPGINTSE); 189 reg &= ~S5P_FINAL_MCU_NUM_INT_EN_MASK; 190 if (enbl) 191 reg |= S5P_FINAL_MCU_NUM_INT_EN; 192 writel(reg, regs + S5P_JPGINTSE); 193 } 194 195 int s5p_jpeg_timer_stat(void __iomem *regs) 196 { 197 return (int)((readl(regs + S5P_JPG_TIMER_ST) & S5P_TIMER_INT_STAT_MASK) 198 >> S5P_TIMER_INT_STAT_SHIFT); 199 } 200 201 void s5p_jpeg_clear_timer_stat(void __iomem *regs) 202 { 203 unsigned long reg; 204 205 reg = readl(regs + S5P_JPG_TIMER_SE); 206 reg &= ~S5P_TIMER_INT_STAT_MASK; 207 writel(reg, regs + S5P_JPG_TIMER_SE); 208 } 209 210 void s5p_jpeg_enc_stream_int(void __iomem *regs, unsigned long size) 211 { 212 unsigned long reg; 213 214 reg = readl(regs + S5P_JPG_ENC_STREAM_INTSE); 215 reg &= ~S5P_ENC_STREAM_BOUND_MASK; 216 reg |= S5P_ENC_STREAM_INT_EN; 217 reg |= size & S5P_ENC_STREAM_BOUND_MASK; 218 writel(reg, regs + S5P_JPG_ENC_STREAM_INTSE); 219 } 220 221 int s5p_jpeg_enc_stream_stat(void __iomem *regs) 222 { 223 return (int)(readl(regs + S5P_JPG_ENC_STREAM_INTST) & 224 S5P_ENC_STREAM_INT_STAT_MASK); 225 } 226 227 void s5p_jpeg_clear_enc_stream_stat(void __iomem *regs) 228 { 229 unsigned long reg; 230 231 reg = readl(regs + S5P_JPG_ENC_STREAM_INTSE); 232 reg &= ~S5P_ENC_STREAM_INT_MASK; 233 writel(reg, regs + S5P_JPG_ENC_STREAM_INTSE); 234 } 235 236 void s5p_jpeg_outform_raw(void __iomem *regs, unsigned long format) 237 { 238 unsigned long reg, f; 239 240 f = S5P_DEC_OUT_FORMAT_422; 241 if (format == S5P_JPEG_RAW_OUT_422) 242 f = S5P_DEC_OUT_FORMAT_422; 243 else if (format == S5P_JPEG_RAW_OUT_420) 244 f = S5P_DEC_OUT_FORMAT_420; 245 reg = readl(regs + S5P_JPG_OUTFORM); 246 reg &= ~S5P_DEC_OUT_FORMAT_MASK; 247 reg |= f; 248 writel(reg, regs + S5P_JPG_OUTFORM); 249 } 250 251 void s5p_jpeg_jpgadr(void __iomem *regs, unsigned long addr) 252 { 253 writel(addr, regs + S5P_JPG_JPGADR); 254 } 255 256 void s5p_jpeg_imgadr(void __iomem *regs, unsigned long addr) 257 { 258 writel(addr, regs + S5P_JPG_IMGADR); 259 } 260 261 void s5p_jpeg_coef(void __iomem *regs, unsigned int i, 262 unsigned int j, unsigned int coef) 263 { 264 unsigned long reg; 265 266 reg = readl(regs + S5P_JPG_COEF(i)); 267 reg &= ~S5P_COEFn_MASK(j); 268 reg |= (coef << S5P_COEFn_SHIFT(j)) & S5P_COEFn_MASK(j); 269 writel(reg, regs + S5P_JPG_COEF(i)); 270 } 271 272 void s5p_jpeg_start(void __iomem *regs) 273 { 274 writel(1, regs + S5P_JSTART); 275 } 276 277 int s5p_jpeg_result_stat_ok(void __iomem *regs) 278 { 279 return (int)((readl(regs + S5P_JPGINTST) & S5P_RESULT_STAT_MASK) 280 >> S5P_RESULT_STAT_SHIFT); 281 } 282 283 int s5p_jpeg_stream_stat_ok(void __iomem *regs) 284 { 285 return !(int)((readl(regs + S5P_JPGINTST) & S5P_STREAM_STAT_MASK) 286 >> S5P_STREAM_STAT_SHIFT); 287 } 288 289 void s5p_jpeg_clear_int(void __iomem *regs) 290 { 291 readl(regs + S5P_JPGINTST); 292 writel(S5P_INT_RELEASE, regs + S5P_JPGCOM); 293 readl(regs + S5P_JPGOPR); 294 } 295 296 unsigned int s5p_jpeg_compressed_size(void __iomem *regs) 297 { 298 unsigned long jpeg_size = 0; 299 300 jpeg_size |= (readl(regs + S5P_JPGCNT_U) & 0xff) << 16; 301 jpeg_size |= (readl(regs + S5P_JPGCNT_M) & 0xff) << 8; 302 jpeg_size |= (readl(regs + S5P_JPGCNT_L) & 0xff); 303 304 return (unsigned int)jpeg_size; 305 } 306