1e6938cc1SHelen Koike // SPDX-License-Identifier: (GPL-2.0+ OR MIT) 2e6938cc1SHelen Koike /* 3e6938cc1SHelen Koike * Rockchip ISP1 Driver - Params subdevice 4e6938cc1SHelen Koike * 5e6938cc1SHelen Koike * Copyright (C) 2017 Rockchip Electronics Co., Ltd. 6e6938cc1SHelen Koike */ 7e6938cc1SHelen Koike 8e6938cc1SHelen Koike #include <media/v4l2-common.h> 9e6938cc1SHelen Koike #include <media/v4l2-event.h> 10e6938cc1SHelen Koike #include <media/v4l2-ioctl.h> 11e6938cc1SHelen Koike #include <media/videobuf2-core.h> 12e6938cc1SHelen Koike #include <media/videobuf2-vmalloc.h> /* for ISP params */ 13e6938cc1SHelen Koike 14e6938cc1SHelen Koike #include "rkisp1-common.h" 15e6938cc1SHelen Koike 16e6938cc1SHelen Koike #define RKISP1_PARAMS_DEV_NAME RKISP1_DRIVER_NAME "_params" 17e6938cc1SHelen Koike 18e6938cc1SHelen Koike #define RKISP1_ISP_PARAMS_REQ_BUFS_MIN 2 19e6938cc1SHelen Koike #define RKISP1_ISP_PARAMS_REQ_BUFS_MAX 8 20e6938cc1SHelen Koike 21596fa6e7SLaurent Pinchart #define RKISP1_ISP_DPCC_METHODS_SET(n) \ 22596fa6e7SLaurent Pinchart (RKISP1_CIF_ISP_DPCC_METHODS_SET_1 + 0x4 * (n)) 23e6938cc1SHelen Koike #define RKISP1_ISP_DPCC_LINE_THRESH(n) \ 24e6938cc1SHelen Koike (RKISP1_CIF_ISP_DPCC_LINE_THRESH_1 + 0x14 * (n)) 25e6938cc1SHelen Koike #define RKISP1_ISP_DPCC_LINE_MAD_FAC(n) \ 26e6938cc1SHelen Koike (RKISP1_CIF_ISP_DPCC_LINE_MAD_FAC_1 + 0x14 * (n)) 27e6938cc1SHelen Koike #define RKISP1_ISP_DPCC_PG_FAC(n) \ 28e6938cc1SHelen Koike (RKISP1_CIF_ISP_DPCC_PG_FAC_1 + 0x14 * (n)) 29e6938cc1SHelen Koike #define RKISP1_ISP_DPCC_RND_THRESH(n) \ 30e6938cc1SHelen Koike (RKISP1_CIF_ISP_DPCC_RND_THRESH_1 + 0x14 * (n)) 31e6938cc1SHelen Koike #define RKISP1_ISP_DPCC_RG_FAC(n) \ 32e6938cc1SHelen Koike (RKISP1_CIF_ISP_DPCC_RG_FAC_1 + 0x14 * (n)) 33e6938cc1SHelen Koike #define RKISP1_ISP_CC_COEFF(n) \ 34e6938cc1SHelen Koike (RKISP1_CIF_ISP_CC_COEFF_0 + (n) * 4) 35e6938cc1SHelen Koike 36e6938cc1SHelen Koike static inline void 37e6938cc1SHelen Koike rkisp1_param_set_bits(struct rkisp1_params *params, u32 reg, u32 bit_mask) 38e6938cc1SHelen Koike { 39e6938cc1SHelen Koike u32 val; 40e6938cc1SHelen Koike 41e6938cc1SHelen Koike val = rkisp1_read(params->rkisp1, reg); 420ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, reg, val | bit_mask); 43e6938cc1SHelen Koike } 44e6938cc1SHelen Koike 45e6938cc1SHelen Koike static inline void 46e6938cc1SHelen Koike rkisp1_param_clear_bits(struct rkisp1_params *params, u32 reg, u32 bit_mask) 47e6938cc1SHelen Koike { 48e6938cc1SHelen Koike u32 val; 49e6938cc1SHelen Koike 50e6938cc1SHelen Koike val = rkisp1_read(params->rkisp1, reg); 510ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, reg, val & ~bit_mask); 52e6938cc1SHelen Koike } 53e6938cc1SHelen Koike 54e6938cc1SHelen Koike /* ISP BP interface function */ 55e6938cc1SHelen Koike static void rkisp1_dpcc_config(struct rkisp1_params *params, 56e6938cc1SHelen Koike const struct rkisp1_cif_isp_dpcc_config *arg) 57e6938cc1SHelen Koike { 58e6938cc1SHelen Koike unsigned int i; 59e6938cc1SHelen Koike u32 mode; 60e6938cc1SHelen Koike 619daa2b84SLaurent Pinchart /* 629daa2b84SLaurent Pinchart * The enable bit is controlled in rkisp1_isp_isr_other_config() and 639daa2b84SLaurent Pinchart * must be preserved. The grayscale mode should be configured 649daa2b84SLaurent Pinchart * automatically based on the media bus code on the ISP sink pad, so 659daa2b84SLaurent Pinchart * only the STAGE1_ENABLE bit can be set by userspace. 669daa2b84SLaurent Pinchart */ 67e6938cc1SHelen Koike mode = rkisp1_read(params->rkisp1, RKISP1_CIF_ISP_DPCC_MODE); 689daa2b84SLaurent Pinchart mode &= RKISP1_CIF_ISP_DPCC_MODE_DPCC_ENABLE; 699daa2b84SLaurent Pinchart mode |= arg->mode & RKISP1_CIF_ISP_DPCC_MODE_STAGE1_ENABLE; 700ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_DPCC_MODE, mode); 719daa2b84SLaurent Pinchart 720ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_DPCC_OUTPUT_MODE, 739daa2b84SLaurent Pinchart arg->output_mode & RKISP1_CIF_ISP_DPCC_OUTPUT_MODE_MASK); 740ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_DPCC_SET_USE, 759daa2b84SLaurent Pinchart arg->set_use & RKISP1_CIF_ISP_DPCC_SET_USE_MASK); 76e6938cc1SHelen Koike 77e6938cc1SHelen Koike for (i = 0; i < RKISP1_CIF_ISP_DPCC_METHODS_MAX; i++) { 78596fa6e7SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_ISP_DPCC_METHODS_SET(i), 799daa2b84SLaurent Pinchart arg->methods[i].method & 809daa2b84SLaurent Pinchart RKISP1_CIF_ISP_DPCC_METHODS_SET_MASK); 810ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_ISP_DPCC_LINE_THRESH(i), 829daa2b84SLaurent Pinchart arg->methods[i].line_thresh & 839daa2b84SLaurent Pinchart RKISP1_CIF_ISP_DPCC_LINE_THRESH_MASK); 840ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_ISP_DPCC_LINE_MAD_FAC(i), 859daa2b84SLaurent Pinchart arg->methods[i].line_mad_fac & 869daa2b84SLaurent Pinchart RKISP1_CIF_ISP_DPCC_LINE_MAD_FAC_MASK); 870ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_ISP_DPCC_PG_FAC(i), 889daa2b84SLaurent Pinchart arg->methods[i].pg_fac & 899daa2b84SLaurent Pinchart RKISP1_CIF_ISP_DPCC_PG_FAC_MASK); 900ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_ISP_DPCC_RND_THRESH(i), 919daa2b84SLaurent Pinchart arg->methods[i].rnd_thresh & 929daa2b84SLaurent Pinchart RKISP1_CIF_ISP_DPCC_RND_THRESH_MASK); 930ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_ISP_DPCC_RG_FAC(i), 949daa2b84SLaurent Pinchart arg->methods[i].rg_fac & 959daa2b84SLaurent Pinchart RKISP1_CIF_ISP_DPCC_RG_FAC_MASK); 96e6938cc1SHelen Koike } 97e6938cc1SHelen Koike 980ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_DPCC_RND_OFFS, 999daa2b84SLaurent Pinchart arg->rnd_offs & RKISP1_CIF_ISP_DPCC_RND_OFFS_MASK); 1000ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_DPCC_RO_LIMITS, 1019daa2b84SLaurent Pinchart arg->ro_limits & RKISP1_CIF_ISP_DPCC_RO_LIMIT_MASK); 102e6938cc1SHelen Koike } 103e6938cc1SHelen Koike 104e6938cc1SHelen Koike /* ISP black level subtraction interface function */ 105e6938cc1SHelen Koike static void rkisp1_bls_config(struct rkisp1_params *params, 106e6938cc1SHelen Koike const struct rkisp1_cif_isp_bls_config *arg) 107e6938cc1SHelen Koike { 108e6938cc1SHelen Koike /* avoid to override the old enable value */ 109e6938cc1SHelen Koike u32 new_control; 110e6938cc1SHelen Koike 111e6938cc1SHelen Koike new_control = rkisp1_read(params->rkisp1, RKISP1_CIF_ISP_BLS_CTRL); 112e6938cc1SHelen Koike new_control &= RKISP1_CIF_ISP_BLS_ENA; 113e6938cc1SHelen Koike /* fixed subtraction values */ 114e6938cc1SHelen Koike if (!arg->enable_auto) { 115e6938cc1SHelen Koike const struct rkisp1_cif_isp_bls_fixed_val *pval = 116e6938cc1SHelen Koike &arg->fixed_val; 117e6938cc1SHelen Koike 118e6938cc1SHelen Koike switch (params->raw_type) { 119e6938cc1SHelen Koike case RKISP1_RAW_BGGR: 1200ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_BLS_D_FIXED, 1210ef7dc30SLaurent Pinchart pval->r); 1220ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_BLS_C_FIXED, 1230ef7dc30SLaurent Pinchart pval->gr); 1240ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_BLS_B_FIXED, 1250ef7dc30SLaurent Pinchart pval->gb); 1260ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_BLS_A_FIXED, 1270ef7dc30SLaurent Pinchart pval->b); 128e6938cc1SHelen Koike break; 129e6938cc1SHelen Koike case RKISP1_RAW_GBRG: 1300ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_BLS_C_FIXED, 1310ef7dc30SLaurent Pinchart pval->r); 1320ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_BLS_D_FIXED, 1330ef7dc30SLaurent Pinchart pval->gr); 1340ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_BLS_A_FIXED, 1350ef7dc30SLaurent Pinchart pval->gb); 1360ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_BLS_B_FIXED, 1370ef7dc30SLaurent Pinchart pval->b); 138e6938cc1SHelen Koike break; 139e6938cc1SHelen Koike case RKISP1_RAW_GRBG: 1400ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_BLS_B_FIXED, 1410ef7dc30SLaurent Pinchart pval->r); 1420ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_BLS_A_FIXED, 1430ef7dc30SLaurent Pinchart pval->gr); 1440ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_BLS_D_FIXED, 1450ef7dc30SLaurent Pinchart pval->gb); 1460ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_BLS_C_FIXED, 1470ef7dc30SLaurent Pinchart pval->b); 148e6938cc1SHelen Koike break; 149e6938cc1SHelen Koike case RKISP1_RAW_RGGB: 1500ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_BLS_A_FIXED, 1510ef7dc30SLaurent Pinchart pval->r); 1520ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_BLS_B_FIXED, 1530ef7dc30SLaurent Pinchart pval->gr); 1540ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_BLS_C_FIXED, 1550ef7dc30SLaurent Pinchart pval->gb); 1560ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_BLS_D_FIXED, 1570ef7dc30SLaurent Pinchart pval->b); 158e6938cc1SHelen Koike break; 159e6938cc1SHelen Koike default: 160e6938cc1SHelen Koike break; 161e6938cc1SHelen Koike } 162e6938cc1SHelen Koike 163e6938cc1SHelen Koike } else { 164e6938cc1SHelen Koike if (arg->en_windows & BIT(1)) { 1650ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_BLS_H2_START, 1660ef7dc30SLaurent Pinchart arg->bls_window2.h_offs); 1670ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_BLS_H2_STOP, 1680ef7dc30SLaurent Pinchart arg->bls_window2.h_size); 1690ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_BLS_V2_START, 1700ef7dc30SLaurent Pinchart arg->bls_window2.v_offs); 1710ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_BLS_V2_STOP, 1720ef7dc30SLaurent Pinchart arg->bls_window2.v_size); 173e6938cc1SHelen Koike new_control |= RKISP1_CIF_ISP_BLS_WINDOW_2; 174e6938cc1SHelen Koike } 175e6938cc1SHelen Koike 176e6938cc1SHelen Koike if (arg->en_windows & BIT(0)) { 1770ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_BLS_H1_START, 1780ef7dc30SLaurent Pinchart arg->bls_window1.h_offs); 1790ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_BLS_H1_STOP, 1800ef7dc30SLaurent Pinchart arg->bls_window1.h_size); 1810ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_BLS_V1_START, 1820ef7dc30SLaurent Pinchart arg->bls_window1.v_offs); 1830ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_BLS_V1_STOP, 1840ef7dc30SLaurent Pinchart arg->bls_window1.v_size); 185e6938cc1SHelen Koike new_control |= RKISP1_CIF_ISP_BLS_WINDOW_1; 186e6938cc1SHelen Koike } 187e6938cc1SHelen Koike 1880ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_BLS_SAMPLES, 1890ef7dc30SLaurent Pinchart arg->bls_samples); 190e6938cc1SHelen Koike 191e6938cc1SHelen Koike new_control |= RKISP1_CIF_ISP_BLS_MODE_MEASURED; 192e6938cc1SHelen Koike } 1930ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_BLS_CTRL, new_control); 194e6938cc1SHelen Koike } 195e6938cc1SHelen Koike 196e6938cc1SHelen Koike /* ISP LS correction interface function */ 197e6938cc1SHelen Koike static void 198dce8ccb2SHeiko Stuebner rkisp1_lsc_matrix_config_v10(struct rkisp1_params *params, 199e6938cc1SHelen Koike const struct rkisp1_cif_isp_lsc_config *pconfig) 200e6938cc1SHelen Koike { 201cf655fafSLaurent Pinchart struct rkisp1_device *rkisp1 = params->rkisp1; 202da57dffaSLaurent Pinchart u32 lsc_status, sram_addr, lsc_table_sel; 203da57dffaSLaurent Pinchart unsigned int i, j; 204e6938cc1SHelen Koike 205cf655fafSLaurent Pinchart lsc_status = rkisp1_read(rkisp1, RKISP1_CIF_ISP_LSC_STATUS); 206e6938cc1SHelen Koike 207e6938cc1SHelen Koike /* RKISP1_CIF_ISP_LSC_TABLE_ADDRESS_153 = ( 17 * 18 ) >> 1 */ 208cf655fafSLaurent Pinchart sram_addr = lsc_status & RKISP1_CIF_ISP_LSC_ACTIVE_TABLE ? 209e6938cc1SHelen Koike RKISP1_CIF_ISP_LSC_TABLE_ADDRESS_0 : 210e6938cc1SHelen Koike RKISP1_CIF_ISP_LSC_TABLE_ADDRESS_153; 211cf655fafSLaurent Pinchart rkisp1_write(rkisp1, RKISP1_CIF_ISP_LSC_R_TABLE_ADDR, sram_addr); 212cf655fafSLaurent Pinchart rkisp1_write(rkisp1, RKISP1_CIF_ISP_LSC_GR_TABLE_ADDR, sram_addr); 213cf655fafSLaurent Pinchart rkisp1_write(rkisp1, RKISP1_CIF_ISP_LSC_GB_TABLE_ADDR, sram_addr); 214cf655fafSLaurent Pinchart rkisp1_write(rkisp1, RKISP1_CIF_ISP_LSC_B_TABLE_ADDR, sram_addr); 215e6938cc1SHelen Koike 216e6938cc1SHelen Koike /* program data tables (table size is 9 * 17 = 153) */ 217e6938cc1SHelen Koike for (i = 0; i < RKISP1_CIF_ISP_LSC_SAMPLES_MAX; i++) { 218cf655fafSLaurent Pinchart const __u16 *r_tbl = pconfig->r_data_tbl[i]; 219cf655fafSLaurent Pinchart const __u16 *gr_tbl = pconfig->gr_data_tbl[i]; 220cf655fafSLaurent Pinchart const __u16 *gb_tbl = pconfig->gb_data_tbl[i]; 221cf655fafSLaurent Pinchart const __u16 *b_tbl = pconfig->b_data_tbl[i]; 222cf655fafSLaurent Pinchart 223e6938cc1SHelen Koike /* 224e6938cc1SHelen Koike * 17 sectors with 2 values in one DWORD = 9 225e6938cc1SHelen Koike * DWORDs (2nd value of last DWORD unused) 226e6938cc1SHelen Koike */ 227e6938cc1SHelen Koike for (j = 0; j < RKISP1_CIF_ISP_LSC_SAMPLES_MAX - 1; j += 2) { 228cf655fafSLaurent Pinchart rkisp1_write(rkisp1, RKISP1_CIF_ISP_LSC_R_TABLE_DATA, 229cf655fafSLaurent Pinchart RKISP1_CIF_ISP_LSC_TABLE_DATA_V10( 230cf655fafSLaurent Pinchart r_tbl[j], r_tbl[j + 1])); 231cf655fafSLaurent Pinchart rkisp1_write(rkisp1, RKISP1_CIF_ISP_LSC_GR_TABLE_DATA, 232cf655fafSLaurent Pinchart RKISP1_CIF_ISP_LSC_TABLE_DATA_V10( 233cf655fafSLaurent Pinchart gr_tbl[j], gr_tbl[j + 1])); 234cf655fafSLaurent Pinchart rkisp1_write(rkisp1, RKISP1_CIF_ISP_LSC_GB_TABLE_DATA, 235cf655fafSLaurent Pinchart RKISP1_CIF_ISP_LSC_TABLE_DATA_V10( 236cf655fafSLaurent Pinchart gb_tbl[j], gb_tbl[j + 1])); 237cf655fafSLaurent Pinchart rkisp1_write(rkisp1, RKISP1_CIF_ISP_LSC_B_TABLE_DATA, 238cf655fafSLaurent Pinchart RKISP1_CIF_ISP_LSC_TABLE_DATA_V10( 239cf655fafSLaurent Pinchart b_tbl[j], b_tbl[j + 1])); 240e6938cc1SHelen Koike } 241e6938cc1SHelen Koike 242cf655fafSLaurent Pinchart rkisp1_write(rkisp1, RKISP1_CIF_ISP_LSC_R_TABLE_DATA, 243cf655fafSLaurent Pinchart RKISP1_CIF_ISP_LSC_TABLE_DATA_V10(r_tbl[j], 0)); 244cf655fafSLaurent Pinchart rkisp1_write(rkisp1, RKISP1_CIF_ISP_LSC_GR_TABLE_DATA, 245cf655fafSLaurent Pinchart RKISP1_CIF_ISP_LSC_TABLE_DATA_V10(gr_tbl[j], 0)); 246cf655fafSLaurent Pinchart rkisp1_write(rkisp1, RKISP1_CIF_ISP_LSC_GB_TABLE_DATA, 247cf655fafSLaurent Pinchart RKISP1_CIF_ISP_LSC_TABLE_DATA_V10(gb_tbl[j], 0)); 248cf655fafSLaurent Pinchart rkisp1_write(rkisp1, RKISP1_CIF_ISP_LSC_B_TABLE_DATA, 249cf655fafSLaurent Pinchart RKISP1_CIF_ISP_LSC_TABLE_DATA_V10(b_tbl[j], 0)); 250e6938cc1SHelen Koike } 251cf655fafSLaurent Pinchart 252cf655fafSLaurent Pinchart lsc_table_sel = lsc_status & RKISP1_CIF_ISP_LSC_ACTIVE_TABLE ? 253cf655fafSLaurent Pinchart RKISP1_CIF_ISP_LSC_TABLE_0 : RKISP1_CIF_ISP_LSC_TABLE_1; 254cf655fafSLaurent Pinchart rkisp1_write(rkisp1, RKISP1_CIF_ISP_LSC_TABLE_SEL, lsc_table_sel); 255e6938cc1SHelen Koike } 256e6938cc1SHelen Koike 257cd42f802SHeiko Stuebner static void 258cd42f802SHeiko Stuebner rkisp1_lsc_matrix_config_v12(struct rkisp1_params *params, 259cd42f802SHeiko Stuebner const struct rkisp1_cif_isp_lsc_config *pconfig) 260cd42f802SHeiko Stuebner { 261cf655fafSLaurent Pinchart struct rkisp1_device *rkisp1 = params->rkisp1; 262da57dffaSLaurent Pinchart u32 lsc_status, sram_addr, lsc_table_sel; 263da57dffaSLaurent Pinchart unsigned int i, j; 264cd42f802SHeiko Stuebner 265cf655fafSLaurent Pinchart lsc_status = rkisp1_read(rkisp1, RKISP1_CIF_ISP_LSC_STATUS); 266cd42f802SHeiko Stuebner 267cd42f802SHeiko Stuebner /* RKISP1_CIF_ISP_LSC_TABLE_ADDRESS_153 = ( 17 * 18 ) >> 1 */ 268cf655fafSLaurent Pinchart sram_addr = lsc_status & RKISP1_CIF_ISP_LSC_ACTIVE_TABLE ? 269cd42f802SHeiko Stuebner RKISP1_CIF_ISP_LSC_TABLE_ADDRESS_0 : 270cd42f802SHeiko Stuebner RKISP1_CIF_ISP_LSC_TABLE_ADDRESS_153; 271cf655fafSLaurent Pinchart rkisp1_write(rkisp1, RKISP1_CIF_ISP_LSC_R_TABLE_ADDR, sram_addr); 272cf655fafSLaurent Pinchart rkisp1_write(rkisp1, RKISP1_CIF_ISP_LSC_GR_TABLE_ADDR, sram_addr); 273cf655fafSLaurent Pinchart rkisp1_write(rkisp1, RKISP1_CIF_ISP_LSC_GB_TABLE_ADDR, sram_addr); 274cf655fafSLaurent Pinchart rkisp1_write(rkisp1, RKISP1_CIF_ISP_LSC_B_TABLE_ADDR, sram_addr); 275cd42f802SHeiko Stuebner 276cd42f802SHeiko Stuebner /* program data tables (table size is 9 * 17 = 153) */ 277cd42f802SHeiko Stuebner for (i = 0; i < RKISP1_CIF_ISP_LSC_SAMPLES_MAX; i++) { 278cf655fafSLaurent Pinchart const __u16 *r_tbl = pconfig->r_data_tbl[i]; 279cf655fafSLaurent Pinchart const __u16 *gr_tbl = pconfig->gr_data_tbl[i]; 280cf655fafSLaurent Pinchart const __u16 *gb_tbl = pconfig->gb_data_tbl[i]; 281cf655fafSLaurent Pinchart const __u16 *b_tbl = pconfig->b_data_tbl[i]; 282cf655fafSLaurent Pinchart 283cd42f802SHeiko Stuebner /* 284cd42f802SHeiko Stuebner * 17 sectors with 2 values in one DWORD = 9 285cd42f802SHeiko Stuebner * DWORDs (2nd value of last DWORD unused) 286cd42f802SHeiko Stuebner */ 287cd42f802SHeiko Stuebner for (j = 0; j < RKISP1_CIF_ISP_LSC_SAMPLES_MAX - 1; j += 2) { 288cf655fafSLaurent Pinchart rkisp1_write(rkisp1, RKISP1_CIF_ISP_LSC_R_TABLE_DATA, 289cf655fafSLaurent Pinchart RKISP1_CIF_ISP_LSC_TABLE_DATA_V12( 290cf655fafSLaurent Pinchart r_tbl[j], r_tbl[j + 1])); 291cf655fafSLaurent Pinchart rkisp1_write(rkisp1, RKISP1_CIF_ISP_LSC_GR_TABLE_DATA, 292cf655fafSLaurent Pinchart RKISP1_CIF_ISP_LSC_TABLE_DATA_V12( 293cf655fafSLaurent Pinchart gr_tbl[j], gr_tbl[j + 1])); 294cf655fafSLaurent Pinchart rkisp1_write(rkisp1, RKISP1_CIF_ISP_LSC_GB_TABLE_DATA, 295cf655fafSLaurent Pinchart RKISP1_CIF_ISP_LSC_TABLE_DATA_V12( 296cf655fafSLaurent Pinchart gb_tbl[j], gb_tbl[j + 1])); 297cf655fafSLaurent Pinchart rkisp1_write(rkisp1, RKISP1_CIF_ISP_LSC_B_TABLE_DATA, 298cf655fafSLaurent Pinchart RKISP1_CIF_ISP_LSC_TABLE_DATA_V12( 299cf655fafSLaurent Pinchart b_tbl[j], b_tbl[j + 1])); 300cd42f802SHeiko Stuebner } 301cd42f802SHeiko Stuebner 302cf655fafSLaurent Pinchart rkisp1_write(rkisp1, RKISP1_CIF_ISP_LSC_R_TABLE_DATA, 303cf655fafSLaurent Pinchart RKISP1_CIF_ISP_LSC_TABLE_DATA_V12(r_tbl[j], 0)); 304cf655fafSLaurent Pinchart rkisp1_write(rkisp1, RKISP1_CIF_ISP_LSC_GR_TABLE_DATA, 305cf655fafSLaurent Pinchart RKISP1_CIF_ISP_LSC_TABLE_DATA_V12(gr_tbl[j], 0)); 306cf655fafSLaurent Pinchart rkisp1_write(rkisp1, RKISP1_CIF_ISP_LSC_GB_TABLE_DATA, 307cf655fafSLaurent Pinchart RKISP1_CIF_ISP_LSC_TABLE_DATA_V12(gb_tbl[j], 0)); 308cf655fafSLaurent Pinchart rkisp1_write(rkisp1, RKISP1_CIF_ISP_LSC_B_TABLE_DATA, 309cf655fafSLaurent Pinchart RKISP1_CIF_ISP_LSC_TABLE_DATA_V12(b_tbl[j], 0)); 310cd42f802SHeiko Stuebner } 311cf655fafSLaurent Pinchart 312cf655fafSLaurent Pinchart lsc_table_sel = lsc_status & RKISP1_CIF_ISP_LSC_ACTIVE_TABLE ? 313cf655fafSLaurent Pinchart RKISP1_CIF_ISP_LSC_TABLE_0 : RKISP1_CIF_ISP_LSC_TABLE_1; 314cf655fafSLaurent Pinchart rkisp1_write(rkisp1, RKISP1_CIF_ISP_LSC_TABLE_SEL, lsc_table_sel); 315cd42f802SHeiko Stuebner } 316cd42f802SHeiko Stuebner 317e6938cc1SHelen Koike static void rkisp1_lsc_config(struct rkisp1_params *params, 318e6938cc1SHelen Koike const struct rkisp1_cif_isp_lsc_config *arg) 319e6938cc1SHelen Koike { 320cf655fafSLaurent Pinchart struct rkisp1_device *rkisp1 = params->rkisp1; 321da57dffaSLaurent Pinchart u32 lsc_ctrl, data; 322da57dffaSLaurent Pinchart unsigned int i; 323e6938cc1SHelen Koike 324e6938cc1SHelen Koike /* To config must be off , store the current status firstly */ 325cf655fafSLaurent Pinchart lsc_ctrl = rkisp1_read(rkisp1, RKISP1_CIF_ISP_LSC_CTRL); 326e6938cc1SHelen Koike rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_LSC_CTRL, 327e6938cc1SHelen Koike RKISP1_CIF_ISP_LSC_CTRL_ENA); 3285e8d9d72SHeiko Stuebner params->ops->lsc_matrix_config(params, arg); 329e6938cc1SHelen Koike 330e6938cc1SHelen Koike for (i = 0; i < RKISP1_CIF_ISP_LSC_SECTORS_TBL_SIZE / 2; i++) { 331e6938cc1SHelen Koike /* program x size tables */ 332e6938cc1SHelen Koike data = RKISP1_CIF_ISP_LSC_SECT_SIZE(arg->x_size_tbl[i * 2], 333e6938cc1SHelen Koike arg->x_size_tbl[i * 2 + 1]); 33410e36b21SLaurent Pinchart rkisp1_write(rkisp1, RKISP1_CIF_ISP_LSC_XSIZE(i), data); 335e6938cc1SHelen Koike 336e6938cc1SHelen Koike /* program x grad tables */ 337*4c3501f1SLaurent Pinchart data = RKISP1_CIF_ISP_LSC_SECT_GRAD(arg->x_grad_tbl[i * 2], 338e6938cc1SHelen Koike arg->x_grad_tbl[i * 2 + 1]); 33910e36b21SLaurent Pinchart rkisp1_write(rkisp1, RKISP1_CIF_ISP_LSC_XGRAD(i), data); 340e6938cc1SHelen Koike 341e6938cc1SHelen Koike /* program y size tables */ 342e6938cc1SHelen Koike data = RKISP1_CIF_ISP_LSC_SECT_SIZE(arg->y_size_tbl[i * 2], 343e6938cc1SHelen Koike arg->y_size_tbl[i * 2 + 1]); 34410e36b21SLaurent Pinchart rkisp1_write(rkisp1, RKISP1_CIF_ISP_LSC_YSIZE(i), data); 345e6938cc1SHelen Koike 346e6938cc1SHelen Koike /* program y grad tables */ 347*4c3501f1SLaurent Pinchart data = RKISP1_CIF_ISP_LSC_SECT_GRAD(arg->y_grad_tbl[i * 2], 348e6938cc1SHelen Koike arg->y_grad_tbl[i * 2 + 1]); 34910e36b21SLaurent Pinchart rkisp1_write(rkisp1, RKISP1_CIF_ISP_LSC_YGRAD(i), data); 350e6938cc1SHelen Koike } 351e6938cc1SHelen Koike 352e6938cc1SHelen Koike /* restore the lsc ctrl status */ 353cf655fafSLaurent Pinchart if (lsc_ctrl & RKISP1_CIF_ISP_LSC_CTRL_ENA) 354cf655fafSLaurent Pinchart rkisp1_param_set_bits(params, RKISP1_CIF_ISP_LSC_CTRL, 355e6938cc1SHelen Koike RKISP1_CIF_ISP_LSC_CTRL_ENA); 356cf655fafSLaurent Pinchart else 357cf655fafSLaurent Pinchart rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_LSC_CTRL, 358e6938cc1SHelen Koike RKISP1_CIF_ISP_LSC_CTRL_ENA); 359e6938cc1SHelen Koike } 360e6938cc1SHelen Koike 361e6938cc1SHelen Koike /* ISP Filtering function */ 362e6938cc1SHelen Koike static void rkisp1_flt_config(struct rkisp1_params *params, 363e6938cc1SHelen Koike const struct rkisp1_cif_isp_flt_config *arg) 364e6938cc1SHelen Koike { 365e6938cc1SHelen Koike u32 filt_mode; 366e6938cc1SHelen Koike 3670ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_FILT_THRESH_BL0, 3680ef7dc30SLaurent Pinchart arg->thresh_bl0); 3690ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_FILT_THRESH_BL1, 3700ef7dc30SLaurent Pinchart arg->thresh_bl1); 3710ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_FILT_THRESH_SH0, 3720ef7dc30SLaurent Pinchart arg->thresh_sh0); 3730ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_FILT_THRESH_SH1, 3740ef7dc30SLaurent Pinchart arg->thresh_sh1); 3750ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_FILT_FAC_BL0, 3760ef7dc30SLaurent Pinchart arg->fac_bl0); 3770ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_FILT_FAC_BL1, 3780ef7dc30SLaurent Pinchart arg->fac_bl1); 3790ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_FILT_FAC_MID, 3800ef7dc30SLaurent Pinchart arg->fac_mid); 3810ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_FILT_FAC_SH0, 3820ef7dc30SLaurent Pinchart arg->fac_sh0); 3830ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_FILT_FAC_SH1, 3840ef7dc30SLaurent Pinchart arg->fac_sh1); 3850ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_FILT_LUM_WEIGHT, 3860ef7dc30SLaurent Pinchart arg->lum_weight); 387e6938cc1SHelen Koike 3880ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_FILT_MODE, 389e6938cc1SHelen Koike (arg->mode ? RKISP1_CIF_ISP_FLT_MODE_DNR : 0) | 390e6938cc1SHelen Koike RKISP1_CIF_ISP_FLT_CHROMA_V_MODE(arg->chr_v_mode) | 391e6938cc1SHelen Koike RKISP1_CIF_ISP_FLT_CHROMA_H_MODE(arg->chr_h_mode) | 3920ef7dc30SLaurent Pinchart RKISP1_CIF_ISP_FLT_GREEN_STAGE1(arg->grn_stage1)); 393e6938cc1SHelen Koike 394e6938cc1SHelen Koike /* avoid to override the old enable value */ 395e6938cc1SHelen Koike filt_mode = rkisp1_read(params->rkisp1, RKISP1_CIF_ISP_FILT_MODE); 396e6938cc1SHelen Koike filt_mode &= RKISP1_CIF_ISP_FLT_ENA; 397e6938cc1SHelen Koike if (arg->mode) 398e6938cc1SHelen Koike filt_mode |= RKISP1_CIF_ISP_FLT_MODE_DNR; 399e6938cc1SHelen Koike filt_mode |= RKISP1_CIF_ISP_FLT_CHROMA_V_MODE(arg->chr_v_mode) | 400e6938cc1SHelen Koike RKISP1_CIF_ISP_FLT_CHROMA_H_MODE(arg->chr_h_mode) | 401e6938cc1SHelen Koike RKISP1_CIF_ISP_FLT_GREEN_STAGE1(arg->grn_stage1); 4020ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_FILT_MODE, filt_mode); 403e6938cc1SHelen Koike } 404e6938cc1SHelen Koike 405e6938cc1SHelen Koike /* ISP demosaic interface function */ 406e6938cc1SHelen Koike static int rkisp1_bdm_config(struct rkisp1_params *params, 407e6938cc1SHelen Koike const struct rkisp1_cif_isp_bdm_config *arg) 408e6938cc1SHelen Koike { 409e6938cc1SHelen Koike u32 bdm_th; 410e6938cc1SHelen Koike 411e6938cc1SHelen Koike /* avoid to override the old enable value */ 412e6938cc1SHelen Koike bdm_th = rkisp1_read(params->rkisp1, RKISP1_CIF_ISP_DEMOSAIC); 413e6938cc1SHelen Koike bdm_th &= RKISP1_CIF_ISP_DEMOSAIC_BYPASS; 414e6938cc1SHelen Koike bdm_th |= arg->demosaic_th & ~RKISP1_CIF_ISP_DEMOSAIC_BYPASS; 415e6938cc1SHelen Koike /* set demosaic threshold */ 4160ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_DEMOSAIC, bdm_th); 417e6938cc1SHelen Koike return 0; 418e6938cc1SHelen Koike } 419e6938cc1SHelen Koike 420e6938cc1SHelen Koike /* ISP GAMMA correction interface function */ 421e6938cc1SHelen Koike static void rkisp1_sdg_config(struct rkisp1_params *params, 422e6938cc1SHelen Koike const struct rkisp1_cif_isp_sdg_config *arg) 423e6938cc1SHelen Koike { 424e6938cc1SHelen Koike unsigned int i; 425e6938cc1SHelen Koike 4260ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_GAMMA_DX_LO, 4270ef7dc30SLaurent Pinchart arg->xa_pnts.gamma_dx0); 4280ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_GAMMA_DX_HI, 4290ef7dc30SLaurent Pinchart arg->xa_pnts.gamma_dx1); 430e6938cc1SHelen Koike 431e6938cc1SHelen Koike for (i = 0; i < RKISP1_CIF_ISP_DEGAMMA_CURVE_SIZE; i++) { 4320ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, 4330ef7dc30SLaurent Pinchart RKISP1_CIF_ISP_GAMMA_R_Y0 + i * 4, 4340ef7dc30SLaurent Pinchart arg->curve_r.gamma_y[i]); 4350ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, 4360ef7dc30SLaurent Pinchart RKISP1_CIF_ISP_GAMMA_G_Y0 + i * 4, 4370ef7dc30SLaurent Pinchart arg->curve_g.gamma_y[i]); 4380ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, 4390ef7dc30SLaurent Pinchart RKISP1_CIF_ISP_GAMMA_B_Y0 + i * 4, 4400ef7dc30SLaurent Pinchart arg->curve_b.gamma_y[i]); 441e6938cc1SHelen Koike } 442e6938cc1SHelen Koike } 443e6938cc1SHelen Koike 444e6938cc1SHelen Koike /* ISP GAMMA correction interface function */ 445dce8ccb2SHeiko Stuebner static void rkisp1_goc_config_v10(struct rkisp1_params *params, 446e6938cc1SHelen Koike const struct rkisp1_cif_isp_goc_config *arg) 447e6938cc1SHelen Koike { 448e6938cc1SHelen Koike unsigned int i; 449e6938cc1SHelen Koike 450e6938cc1SHelen Koike rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_CTRL, 451e6938cc1SHelen Koike RKISP1_CIF_ISP_CTRL_ISP_GAMMA_OUT_ENA); 4520ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_GAMMA_OUT_MODE_V10, 4530ef7dc30SLaurent Pinchart arg->mode); 454e6938cc1SHelen Koike 455ef357e02SHeiko Stuebner for (i = 0; i < RKISP1_CIF_ISP_GAMMA_OUT_MAX_SAMPLES_V10; i++) 4560ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, 4570ef7dc30SLaurent Pinchart RKISP1_CIF_ISP_GAMMA_OUT_Y_0_V10 + i * 4, 4580ef7dc30SLaurent Pinchart arg->gamma_y[i]); 459e6938cc1SHelen Koike } 460e6938cc1SHelen Koike 461cd42f802SHeiko Stuebner static void rkisp1_goc_config_v12(struct rkisp1_params *params, 462cd42f802SHeiko Stuebner const struct rkisp1_cif_isp_goc_config *arg) 463cd42f802SHeiko Stuebner { 464cd42f802SHeiko Stuebner unsigned int i; 465cd42f802SHeiko Stuebner u32 value; 466cd42f802SHeiko Stuebner 467cd42f802SHeiko Stuebner rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_CTRL, 468cd42f802SHeiko Stuebner RKISP1_CIF_ISP_CTRL_ISP_GAMMA_OUT_ENA); 4690ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_GAMMA_OUT_MODE_V12, 4700ef7dc30SLaurent Pinchart arg->mode); 471cd42f802SHeiko Stuebner 472cd42f802SHeiko Stuebner for (i = 0; i < RKISP1_CIF_ISP_GAMMA_OUT_MAX_SAMPLES_V12 / 2; i++) { 473cd42f802SHeiko Stuebner value = RKISP1_CIF_ISP_GAMMA_VALUE_V12( 474cd42f802SHeiko Stuebner arg->gamma_y[2 * i + 1], 475cd42f802SHeiko Stuebner arg->gamma_y[2 * i]); 4760ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, 4770ef7dc30SLaurent Pinchart RKISP1_CIF_ISP_GAMMA_OUT_Y_0_V12 + i * 4, value); 478cd42f802SHeiko Stuebner } 479cd42f802SHeiko Stuebner } 480cd42f802SHeiko Stuebner 481e6938cc1SHelen Koike /* ISP Cross Talk */ 482e6938cc1SHelen Koike static void rkisp1_ctk_config(struct rkisp1_params *params, 483e6938cc1SHelen Koike const struct rkisp1_cif_isp_ctk_config *arg) 484e6938cc1SHelen Koike { 485e6938cc1SHelen Koike unsigned int i, j, k = 0; 486e6938cc1SHelen Koike 487e6938cc1SHelen Koike for (i = 0; i < 3; i++) 488e6938cc1SHelen Koike for (j = 0; j < 3; j++) 4890ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, 4900ef7dc30SLaurent Pinchart RKISP1_CIF_ISP_CT_COEFF_0 + 4 * k++, 4910ef7dc30SLaurent Pinchart arg->coeff[i][j]); 492e6938cc1SHelen Koike for (i = 0; i < 3; i++) 4930ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, 4940ef7dc30SLaurent Pinchart RKISP1_CIF_ISP_CT_OFFSET_R + i * 4, 4950ef7dc30SLaurent Pinchart arg->ct_offset[i]); 496e6938cc1SHelen Koike } 497e6938cc1SHelen Koike 498e6938cc1SHelen Koike static void rkisp1_ctk_enable(struct rkisp1_params *params, bool en) 499e6938cc1SHelen Koike { 500e6938cc1SHelen Koike if (en) 501e6938cc1SHelen Koike return; 502e6938cc1SHelen Koike 503e6938cc1SHelen Koike /* Write back the default values. */ 5040ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_CT_COEFF_0, 0x80); 5050ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_CT_COEFF_1, 0); 5060ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_CT_COEFF_2, 0); 5070ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_CT_COEFF_3, 0); 5080ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_CT_COEFF_4, 0x80); 5090ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_CT_COEFF_5, 0); 5100ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_CT_COEFF_6, 0); 5110ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_CT_COEFF_7, 0); 5120ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_CT_COEFF_8, 0x80); 513e6938cc1SHelen Koike 5140ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_CT_OFFSET_R, 0); 5150ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_CT_OFFSET_G, 0); 5160ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_CT_OFFSET_B, 0); 517e6938cc1SHelen Koike } 518e6938cc1SHelen Koike 519e6938cc1SHelen Koike /* ISP White Balance Mode */ 520dce8ccb2SHeiko Stuebner static void rkisp1_awb_meas_config_v10(struct rkisp1_params *params, 521e6938cc1SHelen Koike const struct rkisp1_cif_isp_awb_meas_config *arg) 522e6938cc1SHelen Koike { 523e6938cc1SHelen Koike u32 reg_val = 0; 524e6938cc1SHelen Koike /* based on the mode,configure the awb module */ 525e6938cc1SHelen Koike if (arg->awb_mode == RKISP1_CIF_ISP_AWB_MODE_YCBCR) { 526e6938cc1SHelen Koike /* Reference Cb and Cr */ 5270ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_AWB_REF_V10, 528e6938cc1SHelen Koike RKISP1_CIF_ISP_AWB_REF_CR_SET(arg->awb_ref_cr) | 5290ef7dc30SLaurent Pinchart arg->awb_ref_cb); 530e6938cc1SHelen Koike /* Yc Threshold */ 5310ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_AWB_THRESH_V10, 532e6938cc1SHelen Koike RKISP1_CIF_ISP_AWB_MAX_Y_SET(arg->max_y) | 533e6938cc1SHelen Koike RKISP1_CIF_ISP_AWB_MIN_Y_SET(arg->min_y) | 534e6938cc1SHelen Koike RKISP1_CIF_ISP_AWB_MAX_CS_SET(arg->max_csum) | 5350ef7dc30SLaurent Pinchart arg->min_c); 536e6938cc1SHelen Koike } 537e6938cc1SHelen Koike 538dce8ccb2SHeiko Stuebner reg_val = rkisp1_read(params->rkisp1, RKISP1_CIF_ISP_AWB_PROP_V10); 539e6938cc1SHelen Koike if (arg->enable_ymax_cmp) 540e6938cc1SHelen Koike reg_val |= RKISP1_CIF_ISP_AWB_YMAX_CMP_EN; 541e6938cc1SHelen Koike else 542e6938cc1SHelen Koike reg_val &= ~RKISP1_CIF_ISP_AWB_YMAX_CMP_EN; 5430ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_AWB_PROP_V10, reg_val); 544e6938cc1SHelen Koike 545e6938cc1SHelen Koike /* window offset */ 5460ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_AWB_WND_V_OFFS_V10, 5470ef7dc30SLaurent Pinchart arg->awb_wnd.v_offs); 5480ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_AWB_WND_H_OFFS_V10, 5490ef7dc30SLaurent Pinchart arg->awb_wnd.h_offs); 550e6938cc1SHelen Koike /* AWB window size */ 5510ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_AWB_WND_V_SIZE_V10, 5520ef7dc30SLaurent Pinchart arg->awb_wnd.v_size); 5530ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_AWB_WND_H_SIZE_V10, 5540ef7dc30SLaurent Pinchart arg->awb_wnd.h_size); 555e6938cc1SHelen Koike /* Number of frames */ 5560ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_AWB_FRAMES_V10, 5570ef7dc30SLaurent Pinchart arg->frames); 558e6938cc1SHelen Koike } 559e6938cc1SHelen Koike 560cd42f802SHeiko Stuebner static void rkisp1_awb_meas_config_v12(struct rkisp1_params *params, 561cd42f802SHeiko Stuebner const struct rkisp1_cif_isp_awb_meas_config *arg) 562cd42f802SHeiko Stuebner { 563cd42f802SHeiko Stuebner u32 reg_val = 0; 564cd42f802SHeiko Stuebner /* based on the mode,configure the awb module */ 565cd42f802SHeiko Stuebner if (arg->awb_mode == RKISP1_CIF_ISP_AWB_MODE_YCBCR) { 566cd42f802SHeiko Stuebner /* Reference Cb and Cr */ 5670ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_AWB_REF_V12, 568cd42f802SHeiko Stuebner RKISP1_CIF_ISP_AWB_REF_CR_SET(arg->awb_ref_cr) | 5690ef7dc30SLaurent Pinchart arg->awb_ref_cb); 570cd42f802SHeiko Stuebner /* Yc Threshold */ 5710ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_AWB_THRESH_V12, 572cd42f802SHeiko Stuebner RKISP1_CIF_ISP_AWB_MAX_Y_SET(arg->max_y) | 573cd42f802SHeiko Stuebner RKISP1_CIF_ISP_AWB_MIN_Y_SET(arg->min_y) | 574cd42f802SHeiko Stuebner RKISP1_CIF_ISP_AWB_MAX_CS_SET(arg->max_csum) | 5750ef7dc30SLaurent Pinchart arg->min_c); 576cd42f802SHeiko Stuebner } 577cd42f802SHeiko Stuebner 578cd42f802SHeiko Stuebner reg_val = rkisp1_read(params->rkisp1, RKISP1_CIF_ISP_AWB_PROP_V12); 579cd42f802SHeiko Stuebner if (arg->enable_ymax_cmp) 580cd42f802SHeiko Stuebner reg_val |= RKISP1_CIF_ISP_AWB_YMAX_CMP_EN; 581cd42f802SHeiko Stuebner else 582cd42f802SHeiko Stuebner reg_val &= ~RKISP1_CIF_ISP_AWB_YMAX_CMP_EN; 583cd42f802SHeiko Stuebner reg_val &= ~RKISP1_CIF_ISP_AWB_SET_FRAMES_MASK_V12; 584cd42f802SHeiko Stuebner reg_val |= RKISP1_CIF_ISP_AWB_SET_FRAMES_V12(arg->frames); 5850ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_AWB_PROP_V12, reg_val); 586cd42f802SHeiko Stuebner 587cd42f802SHeiko Stuebner /* window offset */ 5880ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_AWB_OFFS_V12, 5890ef7dc30SLaurent Pinchart arg->awb_wnd.v_offs << 16 | arg->awb_wnd.h_offs); 590cd42f802SHeiko Stuebner /* AWB window size */ 5910ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_AWB_SIZE_V12, 5920ef7dc30SLaurent Pinchart arg->awb_wnd.v_size << 16 | arg->awb_wnd.h_size); 593cd42f802SHeiko Stuebner } 594cd42f802SHeiko Stuebner 595e6938cc1SHelen Koike static void 596dce8ccb2SHeiko Stuebner rkisp1_awb_meas_enable_v10(struct rkisp1_params *params, 597e6938cc1SHelen Koike const struct rkisp1_cif_isp_awb_meas_config *arg, 598e6938cc1SHelen Koike bool en) 599e6938cc1SHelen Koike { 600dce8ccb2SHeiko Stuebner u32 reg_val = rkisp1_read(params->rkisp1, RKISP1_CIF_ISP_AWB_PROP_V10); 601e6938cc1SHelen Koike 602e6938cc1SHelen Koike /* switch off */ 603e6938cc1SHelen Koike reg_val &= RKISP1_CIF_ISP_AWB_MODE_MASK_NONE; 604e6938cc1SHelen Koike 605e6938cc1SHelen Koike if (en) { 606e6938cc1SHelen Koike if (arg->awb_mode == RKISP1_CIF_ISP_AWB_MODE_RGB) 607e6938cc1SHelen Koike reg_val |= RKISP1_CIF_ISP_AWB_MODE_RGB_EN; 608e6938cc1SHelen Koike else 609e6938cc1SHelen Koike reg_val |= RKISP1_CIF_ISP_AWB_MODE_YCBCR_EN; 610e6938cc1SHelen Koike 6110ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_AWB_PROP_V10, 6120ef7dc30SLaurent Pinchart reg_val); 613e6938cc1SHelen Koike 614e6938cc1SHelen Koike /* Measurements require AWB block be active. */ 615e6938cc1SHelen Koike rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL, 616e6938cc1SHelen Koike RKISP1_CIF_ISP_CTRL_ISP_AWB_ENA); 617e6938cc1SHelen Koike } else { 6180ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_AWB_PROP_V10, 6190ef7dc30SLaurent Pinchart reg_val); 620e6938cc1SHelen Koike rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_CTRL, 621e6938cc1SHelen Koike RKISP1_CIF_ISP_CTRL_ISP_AWB_ENA); 622e6938cc1SHelen Koike } 623e6938cc1SHelen Koike } 624e6938cc1SHelen Koike 625e6938cc1SHelen Koike static void 626cd42f802SHeiko Stuebner rkisp1_awb_meas_enable_v12(struct rkisp1_params *params, 627cd42f802SHeiko Stuebner const struct rkisp1_cif_isp_awb_meas_config *arg, 628cd42f802SHeiko Stuebner bool en) 629cd42f802SHeiko Stuebner { 630cd42f802SHeiko Stuebner u32 reg_val = rkisp1_read(params->rkisp1, RKISP1_CIF_ISP_AWB_PROP_V12); 631cd42f802SHeiko Stuebner 632cd42f802SHeiko Stuebner /* switch off */ 633cd42f802SHeiko Stuebner reg_val &= RKISP1_CIF_ISP_AWB_MODE_MASK_NONE; 634cd42f802SHeiko Stuebner 635cd42f802SHeiko Stuebner if (en) { 636cd42f802SHeiko Stuebner if (arg->awb_mode == RKISP1_CIF_ISP_AWB_MODE_RGB) 637cd42f802SHeiko Stuebner reg_val |= RKISP1_CIF_ISP_AWB_MODE_RGB_EN; 638cd42f802SHeiko Stuebner else 639cd42f802SHeiko Stuebner reg_val |= RKISP1_CIF_ISP_AWB_MODE_YCBCR_EN; 640cd42f802SHeiko Stuebner 6410ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_AWB_PROP_V12, 6420ef7dc30SLaurent Pinchart reg_val); 643cd42f802SHeiko Stuebner 644cd42f802SHeiko Stuebner /* Measurements require AWB block be active. */ 645cd42f802SHeiko Stuebner rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL, 646cd42f802SHeiko Stuebner RKISP1_CIF_ISP_CTRL_ISP_AWB_ENA); 647cd42f802SHeiko Stuebner } else { 6480ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_AWB_PROP_V12, 6490ef7dc30SLaurent Pinchart reg_val); 650cd42f802SHeiko Stuebner rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_CTRL, 651cd42f802SHeiko Stuebner RKISP1_CIF_ISP_CTRL_ISP_AWB_ENA); 652cd42f802SHeiko Stuebner } 653cd42f802SHeiko Stuebner } 654cd42f802SHeiko Stuebner 655cd42f802SHeiko Stuebner static void 656dce8ccb2SHeiko Stuebner rkisp1_awb_gain_config_v10(struct rkisp1_params *params, 657e6938cc1SHelen Koike const struct rkisp1_cif_isp_awb_gain_config *arg) 658e6938cc1SHelen Koike { 6590ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_AWB_GAIN_G_V10, 660e6938cc1SHelen Koike RKISP1_CIF_ISP_AWB_GAIN_R_SET(arg->gain_green_r) | 6610ef7dc30SLaurent Pinchart arg->gain_green_b); 662e6938cc1SHelen Koike 6630ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_AWB_GAIN_RB_V10, 664e6938cc1SHelen Koike RKISP1_CIF_ISP_AWB_GAIN_R_SET(arg->gain_red) | 6650ef7dc30SLaurent Pinchart arg->gain_blue); 666e6938cc1SHelen Koike } 667e6938cc1SHelen Koike 668cd42f802SHeiko Stuebner static void 669cd42f802SHeiko Stuebner rkisp1_awb_gain_config_v12(struct rkisp1_params *params, 670cd42f802SHeiko Stuebner const struct rkisp1_cif_isp_awb_gain_config *arg) 671cd42f802SHeiko Stuebner { 6720ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_AWB_GAIN_G_V12, 673cd42f802SHeiko Stuebner RKISP1_CIF_ISP_AWB_GAIN_R_SET(arg->gain_green_r) | 6740ef7dc30SLaurent Pinchart arg->gain_green_b); 675cd42f802SHeiko Stuebner 6760ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_AWB_GAIN_RB_V12, 677cd42f802SHeiko Stuebner RKISP1_CIF_ISP_AWB_GAIN_R_SET(arg->gain_red) | 6780ef7dc30SLaurent Pinchart arg->gain_blue); 679cd42f802SHeiko Stuebner } 680cd42f802SHeiko Stuebner 681dce8ccb2SHeiko Stuebner static void rkisp1_aec_config_v10(struct rkisp1_params *params, 682e6938cc1SHelen Koike const struct rkisp1_cif_isp_aec_config *arg) 683e6938cc1SHelen Koike { 684e6938cc1SHelen Koike unsigned int block_hsize, block_vsize; 685e6938cc1SHelen Koike u32 exp_ctrl; 686e6938cc1SHelen Koike 687e6938cc1SHelen Koike /* avoid to override the old enable value */ 688e6938cc1SHelen Koike exp_ctrl = rkisp1_read(params->rkisp1, RKISP1_CIF_ISP_EXP_CTRL); 689e6938cc1SHelen Koike exp_ctrl &= RKISP1_CIF_ISP_EXP_ENA; 690e6938cc1SHelen Koike if (arg->autostop) 691e6938cc1SHelen Koike exp_ctrl |= RKISP1_CIF_ISP_EXP_CTRL_AUTOSTOP; 692e6938cc1SHelen Koike if (arg->mode == RKISP1_CIF_ISP_EXP_MEASURING_MODE_1) 693e6938cc1SHelen Koike exp_ctrl |= RKISP1_CIF_ISP_EXP_CTRL_MEASMODE_1; 6940ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_EXP_CTRL, exp_ctrl); 695e6938cc1SHelen Koike 6960ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_EXP_H_OFFSET_V10, 6970ef7dc30SLaurent Pinchart arg->meas_window.h_offs); 6980ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_EXP_V_OFFSET_V10, 6990ef7dc30SLaurent Pinchart arg->meas_window.v_offs); 700e6938cc1SHelen Koike 701e6938cc1SHelen Koike block_hsize = arg->meas_window.h_size / 702dce8ccb2SHeiko Stuebner RKISP1_CIF_ISP_EXP_COLUMN_NUM_V10 - 1; 703e6938cc1SHelen Koike block_vsize = arg->meas_window.v_size / 704dce8ccb2SHeiko Stuebner RKISP1_CIF_ISP_EXP_ROW_NUM_V10 - 1; 705e6938cc1SHelen Koike 7060ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_EXP_H_SIZE_V10, 7070ef7dc30SLaurent Pinchart RKISP1_CIF_ISP_EXP_H_SIZE_SET_V10(block_hsize)); 7080ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_EXP_V_SIZE_V10, 7090ef7dc30SLaurent Pinchart RKISP1_CIF_ISP_EXP_V_SIZE_SET_V10(block_vsize)); 710e6938cc1SHelen Koike } 711e6938cc1SHelen Koike 712cd42f802SHeiko Stuebner static void rkisp1_aec_config_v12(struct rkisp1_params *params, 713cd42f802SHeiko Stuebner const struct rkisp1_cif_isp_aec_config *arg) 714cd42f802SHeiko Stuebner { 715cd42f802SHeiko Stuebner u32 exp_ctrl; 716cd42f802SHeiko Stuebner u32 block_hsize, block_vsize; 717cd42f802SHeiko Stuebner u32 wnd_num_idx = 1; 718cd42f802SHeiko Stuebner const u32 ae_wnd_num[] = { 5, 9, 15, 15 }; 719cd42f802SHeiko Stuebner 720cd42f802SHeiko Stuebner /* avoid to override the old enable value */ 721cd42f802SHeiko Stuebner exp_ctrl = rkisp1_read(params->rkisp1, RKISP1_CIF_ISP_EXP_CTRL); 722cd42f802SHeiko Stuebner exp_ctrl &= RKISP1_CIF_ISP_EXP_ENA; 723cd42f802SHeiko Stuebner if (arg->autostop) 724cd42f802SHeiko Stuebner exp_ctrl |= RKISP1_CIF_ISP_EXP_CTRL_AUTOSTOP; 725cd42f802SHeiko Stuebner if (arg->mode == RKISP1_CIF_ISP_EXP_MEASURING_MODE_1) 726cd42f802SHeiko Stuebner exp_ctrl |= RKISP1_CIF_ISP_EXP_CTRL_MEASMODE_1; 727cd42f802SHeiko Stuebner exp_ctrl |= RKISP1_CIF_ISP_EXP_CTRL_WNDNUM_SET_V12(wnd_num_idx); 7280ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_EXP_CTRL, exp_ctrl); 729cd42f802SHeiko Stuebner 7300ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_EXP_OFFS_V12, 731cd42f802SHeiko Stuebner RKISP1_CIF_ISP_EXP_V_OFFSET_SET_V12(arg->meas_window.v_offs) | 7320ef7dc30SLaurent Pinchart RKISP1_CIF_ISP_EXP_H_OFFSET_SET_V12(arg->meas_window.h_offs)); 733cd42f802SHeiko Stuebner 734cd42f802SHeiko Stuebner block_hsize = arg->meas_window.h_size / ae_wnd_num[wnd_num_idx] - 1; 735cd42f802SHeiko Stuebner block_vsize = arg->meas_window.v_size / ae_wnd_num[wnd_num_idx] - 1; 736cd42f802SHeiko Stuebner 7370ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_EXP_SIZE_V12, 738cd42f802SHeiko Stuebner RKISP1_CIF_ISP_EXP_V_SIZE_SET_V12(block_vsize) | 7390ef7dc30SLaurent Pinchart RKISP1_CIF_ISP_EXP_H_SIZE_SET_V12(block_hsize)); 740cd42f802SHeiko Stuebner } 741cd42f802SHeiko Stuebner 742e6938cc1SHelen Koike static void rkisp1_cproc_config(struct rkisp1_params *params, 743e6938cc1SHelen Koike const struct rkisp1_cif_isp_cproc_config *arg) 744e6938cc1SHelen Koike { 745e6938cc1SHelen Koike struct rkisp1_cif_isp_isp_other_cfg *cur_other_cfg = 746e6938cc1SHelen Koike container_of(arg, struct rkisp1_cif_isp_isp_other_cfg, cproc_config); 747e6938cc1SHelen Koike struct rkisp1_cif_isp_ie_config *cur_ie_config = 748e6938cc1SHelen Koike &cur_other_cfg->ie_config; 749e6938cc1SHelen Koike u32 effect = cur_ie_config->effect; 750e6938cc1SHelen Koike u32 quantization = params->quantization; 751e6938cc1SHelen Koike 7520ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_C_PROC_CONTRAST, 7530ef7dc30SLaurent Pinchart arg->contrast); 7540ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_C_PROC_HUE, arg->hue); 7550ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_C_PROC_SATURATION, arg->sat); 7560ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_C_PROC_BRIGHTNESS, 7570ef7dc30SLaurent Pinchart arg->brightness); 758e6938cc1SHelen Koike 759e6938cc1SHelen Koike if (quantization != V4L2_QUANTIZATION_FULL_RANGE || 760e6938cc1SHelen Koike effect != V4L2_COLORFX_NONE) { 761e6938cc1SHelen Koike rkisp1_param_clear_bits(params, RKISP1_CIF_C_PROC_CTRL, 762e6938cc1SHelen Koike RKISP1_CIF_C_PROC_YOUT_FULL | 763e6938cc1SHelen Koike RKISP1_CIF_C_PROC_YIN_FULL | 764e6938cc1SHelen Koike RKISP1_CIF_C_PROC_COUT_FULL); 765e6938cc1SHelen Koike } else { 766e6938cc1SHelen Koike rkisp1_param_set_bits(params, RKISP1_CIF_C_PROC_CTRL, 767e6938cc1SHelen Koike RKISP1_CIF_C_PROC_YOUT_FULL | 768e6938cc1SHelen Koike RKISP1_CIF_C_PROC_YIN_FULL | 769e6938cc1SHelen Koike RKISP1_CIF_C_PROC_COUT_FULL); 770e6938cc1SHelen Koike } 771e6938cc1SHelen Koike } 772e6938cc1SHelen Koike 773dce8ccb2SHeiko Stuebner static void rkisp1_hst_config_v10(struct rkisp1_params *params, 774e6938cc1SHelen Koike const struct rkisp1_cif_isp_hst_config *arg) 775e6938cc1SHelen Koike { 776e6938cc1SHelen Koike unsigned int block_hsize, block_vsize; 777e6938cc1SHelen Koike static const u32 hist_weight_regs[] = { 778dce8ccb2SHeiko Stuebner RKISP1_CIF_ISP_HIST_WEIGHT_00TO30_V10, 779dce8ccb2SHeiko Stuebner RKISP1_CIF_ISP_HIST_WEIGHT_40TO21_V10, 780dce8ccb2SHeiko Stuebner RKISP1_CIF_ISP_HIST_WEIGHT_31TO12_V10, 781dce8ccb2SHeiko Stuebner RKISP1_CIF_ISP_HIST_WEIGHT_22TO03_V10, 782dce8ccb2SHeiko Stuebner RKISP1_CIF_ISP_HIST_WEIGHT_13TO43_V10, 783dce8ccb2SHeiko Stuebner RKISP1_CIF_ISP_HIST_WEIGHT_04TO34_V10, 784e6938cc1SHelen Koike }; 785e6938cc1SHelen Koike const u8 *weight; 786e6938cc1SHelen Koike unsigned int i; 787e6938cc1SHelen Koike u32 hist_prop; 788e6938cc1SHelen Koike 789e6938cc1SHelen Koike /* avoid to override the old enable value */ 790dce8ccb2SHeiko Stuebner hist_prop = rkisp1_read(params->rkisp1, RKISP1_CIF_ISP_HIST_PROP_V10); 791dce8ccb2SHeiko Stuebner hist_prop &= RKISP1_CIF_ISP_HIST_PROP_MODE_MASK_V10; 792dce8ccb2SHeiko Stuebner hist_prop |= RKISP1_CIF_ISP_HIST_PREDIV_SET_V10(arg->histogram_predivider); 7930ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_HIST_PROP_V10, hist_prop); 7940ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_HIST_H_OFFS_V10, 7950ef7dc30SLaurent Pinchart arg->meas_window.h_offs); 7960ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_HIST_V_OFFS_V10, 7970ef7dc30SLaurent Pinchart arg->meas_window.v_offs); 798e6938cc1SHelen Koike 799e6938cc1SHelen Koike block_hsize = arg->meas_window.h_size / 800dce8ccb2SHeiko Stuebner RKISP1_CIF_ISP_HIST_COLUMN_NUM_V10 - 1; 801dce8ccb2SHeiko Stuebner block_vsize = arg->meas_window.v_size / RKISP1_CIF_ISP_HIST_ROW_NUM_V10 - 1; 802e6938cc1SHelen Koike 8030ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_HIST_H_SIZE_V10, 8040ef7dc30SLaurent Pinchart block_hsize); 8050ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_HIST_V_SIZE_V10, 8060ef7dc30SLaurent Pinchart block_vsize); 807e6938cc1SHelen Koike 808e6938cc1SHelen Koike weight = arg->hist_weight; 809e6938cc1SHelen Koike for (i = 0; i < ARRAY_SIZE(hist_weight_regs); ++i, weight += 4) 8100ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, hist_weight_regs[i], 8110ef7dc30SLaurent Pinchart RKISP1_CIF_ISP_HIST_WEIGHT_SET_V10(weight[0], weight[1], 8120ef7dc30SLaurent Pinchart weight[2], weight[3])); 81366d81de7SHeiko Stuebner 8140ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_HIST_WEIGHT_44_V10, 8150ef7dc30SLaurent Pinchart weight[0] & 0x1F); 816e6938cc1SHelen Koike } 817e6938cc1SHelen Koike 818cd42f802SHeiko Stuebner static void rkisp1_hst_config_v12(struct rkisp1_params *params, 819cd42f802SHeiko Stuebner const struct rkisp1_cif_isp_hst_config *arg) 820cd42f802SHeiko Stuebner { 821cd42f802SHeiko Stuebner unsigned int i, j; 822cd42f802SHeiko Stuebner u32 block_hsize, block_vsize; 823cd42f802SHeiko Stuebner u32 wnd_num_idx, hist_weight_num, hist_ctrl, value; 824cd42f802SHeiko Stuebner u8 weight15x15[RKISP1_CIF_ISP_HIST_WEIGHT_REG_SIZE_V12]; 825cd42f802SHeiko Stuebner const u32 hist_wnd_num[] = { 5, 9, 15, 15 }; 826cd42f802SHeiko Stuebner 827cd42f802SHeiko Stuebner /* now we just support 9x9 window */ 828cd42f802SHeiko Stuebner wnd_num_idx = 1; 829cd42f802SHeiko Stuebner memset(weight15x15, 0x00, sizeof(weight15x15)); 830cd42f802SHeiko Stuebner /* avoid to override the old enable value */ 831cd42f802SHeiko Stuebner hist_ctrl = rkisp1_read(params->rkisp1, RKISP1_CIF_ISP_HIST_CTRL_V12); 832cd42f802SHeiko Stuebner hist_ctrl &= RKISP1_CIF_ISP_HIST_CTRL_MODE_MASK_V12 | 833cd42f802SHeiko Stuebner RKISP1_CIF_ISP_HIST_CTRL_EN_MASK_V12; 834cd42f802SHeiko Stuebner hist_ctrl = hist_ctrl | 835cd42f802SHeiko Stuebner RKISP1_CIF_ISP_HIST_CTRL_INTRSEL_SET_V12(1) | 836cd42f802SHeiko Stuebner RKISP1_CIF_ISP_HIST_CTRL_DATASEL_SET_V12(0) | 837cd42f802SHeiko Stuebner RKISP1_CIF_ISP_HIST_CTRL_WATERLINE_SET_V12(0) | 838cd42f802SHeiko Stuebner RKISP1_CIF_ISP_HIST_CTRL_AUTOSTOP_SET_V12(0) | 839cd42f802SHeiko Stuebner RKISP1_CIF_ISP_HIST_CTRL_WNDNUM_SET_V12(1) | 840cd42f802SHeiko Stuebner RKISP1_CIF_ISP_HIST_CTRL_STEPSIZE_SET_V12(arg->histogram_predivider); 8410ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_HIST_CTRL_V12, hist_ctrl); 842cd42f802SHeiko Stuebner 8430ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_HIST_OFFS_V12, 844cd42f802SHeiko Stuebner RKISP1_CIF_ISP_HIST_OFFS_SET_V12(arg->meas_window.h_offs, 8450ef7dc30SLaurent Pinchart arg->meas_window.v_offs)); 846cd42f802SHeiko Stuebner 847cd42f802SHeiko Stuebner block_hsize = arg->meas_window.h_size / hist_wnd_num[wnd_num_idx] - 1; 848cd42f802SHeiko Stuebner block_vsize = arg->meas_window.v_size / hist_wnd_num[wnd_num_idx] - 1; 8490ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_HIST_SIZE_V12, 8500ef7dc30SLaurent Pinchart RKISP1_CIF_ISP_HIST_SIZE_SET_V12(block_hsize, block_vsize)); 851cd42f802SHeiko Stuebner 852cd42f802SHeiko Stuebner for (i = 0; i < hist_wnd_num[wnd_num_idx]; i++) { 853cd42f802SHeiko Stuebner for (j = 0; j < hist_wnd_num[wnd_num_idx]; j++) { 854cd42f802SHeiko Stuebner weight15x15[i * RKISP1_CIF_ISP_HIST_ROW_NUM_V12 + j] = 855cd42f802SHeiko Stuebner arg->hist_weight[i * hist_wnd_num[wnd_num_idx] + j]; 856cd42f802SHeiko Stuebner } 857cd42f802SHeiko Stuebner } 858cd42f802SHeiko Stuebner 859cd42f802SHeiko Stuebner hist_weight_num = RKISP1_CIF_ISP_HIST_WEIGHT_REG_SIZE_V12; 860cd42f802SHeiko Stuebner for (i = 0; i < (hist_weight_num / 4); i++) { 861cd42f802SHeiko Stuebner value = RKISP1_CIF_ISP_HIST_WEIGHT_SET_V12( 862cd42f802SHeiko Stuebner weight15x15[4 * i + 0], 863cd42f802SHeiko Stuebner weight15x15[4 * i + 1], 864cd42f802SHeiko Stuebner weight15x15[4 * i + 2], 865cd42f802SHeiko Stuebner weight15x15[4 * i + 3]); 8660ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, 8670ef7dc30SLaurent Pinchart RKISP1_CIF_ISP_HIST_WEIGHT_V12 + 4 * i, value); 868cd42f802SHeiko Stuebner } 869cd42f802SHeiko Stuebner value = RKISP1_CIF_ISP_HIST_WEIGHT_SET_V12(weight15x15[4 * i + 0], 0, 0, 0); 8700ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_HIST_WEIGHT_V12 + 4 * i, 8710ef7dc30SLaurent Pinchart value); 872cd42f802SHeiko Stuebner } 873cd42f802SHeiko Stuebner 874e6938cc1SHelen Koike static void 875dce8ccb2SHeiko Stuebner rkisp1_hst_enable_v10(struct rkisp1_params *params, 876e6938cc1SHelen Koike const struct rkisp1_cif_isp_hst_config *arg, bool en) 877e6938cc1SHelen Koike { 878e6938cc1SHelen Koike if (en) { 879e6938cc1SHelen Koike u32 hist_prop = rkisp1_read(params->rkisp1, 880dce8ccb2SHeiko Stuebner RKISP1_CIF_ISP_HIST_PROP_V10); 881e6938cc1SHelen Koike 882dce8ccb2SHeiko Stuebner hist_prop &= ~RKISP1_CIF_ISP_HIST_PROP_MODE_MASK_V10; 883e6938cc1SHelen Koike hist_prop |= arg->mode; 884dce8ccb2SHeiko Stuebner rkisp1_param_set_bits(params, RKISP1_CIF_ISP_HIST_PROP_V10, 885e6938cc1SHelen Koike hist_prop); 886e6938cc1SHelen Koike } else { 887dce8ccb2SHeiko Stuebner rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_HIST_PROP_V10, 888dce8ccb2SHeiko Stuebner RKISP1_CIF_ISP_HIST_PROP_MODE_MASK_V10); 889e6938cc1SHelen Koike } 890e6938cc1SHelen Koike } 891e6938cc1SHelen Koike 892cd42f802SHeiko Stuebner static void 893cd42f802SHeiko Stuebner rkisp1_hst_enable_v12(struct rkisp1_params *params, 894cd42f802SHeiko Stuebner const struct rkisp1_cif_isp_hst_config *arg, bool en) 895cd42f802SHeiko Stuebner { 896cd42f802SHeiko Stuebner if (en) { 897cd42f802SHeiko Stuebner u32 hist_ctrl = rkisp1_read(params->rkisp1, 898cd42f802SHeiko Stuebner RKISP1_CIF_ISP_HIST_CTRL_V12); 899cd42f802SHeiko Stuebner 900cd42f802SHeiko Stuebner hist_ctrl &= ~RKISP1_CIF_ISP_HIST_CTRL_MODE_MASK_V12; 901cd42f802SHeiko Stuebner hist_ctrl |= RKISP1_CIF_ISP_HIST_CTRL_MODE_SET_V12(arg->mode); 902cd42f802SHeiko Stuebner hist_ctrl |= RKISP1_CIF_ISP_HIST_CTRL_EN_SET_V12(1); 903cd42f802SHeiko Stuebner rkisp1_param_set_bits(params, RKISP1_CIF_ISP_HIST_CTRL_V12, 904cd42f802SHeiko Stuebner hist_ctrl); 905cd42f802SHeiko Stuebner } else { 906cd42f802SHeiko Stuebner rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_HIST_CTRL_V12, 907cd42f802SHeiko Stuebner RKISP1_CIF_ISP_HIST_CTRL_MODE_MASK_V12 | 908cd42f802SHeiko Stuebner RKISP1_CIF_ISP_HIST_CTRL_EN_MASK_V12); 909cd42f802SHeiko Stuebner } 910cd42f802SHeiko Stuebner } 911cd42f802SHeiko Stuebner 912dce8ccb2SHeiko Stuebner static void rkisp1_afm_config_v10(struct rkisp1_params *params, 913e6938cc1SHelen Koike const struct rkisp1_cif_isp_afc_config *arg) 914e6938cc1SHelen Koike { 915e6938cc1SHelen Koike size_t num_of_win = min_t(size_t, ARRAY_SIZE(arg->afm_win), 916e6938cc1SHelen Koike arg->num_afm_win); 917e6938cc1SHelen Koike u32 afm_ctrl = rkisp1_read(params->rkisp1, RKISP1_CIF_ISP_AFM_CTRL); 918e6938cc1SHelen Koike unsigned int i; 919e6938cc1SHelen Koike 920e6938cc1SHelen Koike /* Switch off to configure. */ 921e6938cc1SHelen Koike rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_AFM_CTRL, 922e6938cc1SHelen Koike RKISP1_CIF_ISP_AFM_ENA); 923e6938cc1SHelen Koike 924e6938cc1SHelen Koike for (i = 0; i < num_of_win; i++) { 9250ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_AFM_LT_A + i * 8, 926e6938cc1SHelen Koike RKISP1_CIF_ISP_AFM_WINDOW_X(arg->afm_win[i].h_offs) | 9270ef7dc30SLaurent Pinchart RKISP1_CIF_ISP_AFM_WINDOW_Y(arg->afm_win[i].v_offs)); 9280ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_AFM_RB_A + i * 8, 929e6938cc1SHelen Koike RKISP1_CIF_ISP_AFM_WINDOW_X(arg->afm_win[i].h_size + 930e6938cc1SHelen Koike arg->afm_win[i].h_offs) | 931e6938cc1SHelen Koike RKISP1_CIF_ISP_AFM_WINDOW_Y(arg->afm_win[i].v_size + 9320ef7dc30SLaurent Pinchart arg->afm_win[i].v_offs)); 933e6938cc1SHelen Koike } 9340ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_AFM_THRES, arg->thres); 9350ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_AFM_VAR_SHIFT, 9360ef7dc30SLaurent Pinchart arg->var_shift); 937e6938cc1SHelen Koike /* restore afm status */ 9380ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_AFM_CTRL, afm_ctrl); 939e6938cc1SHelen Koike } 940e6938cc1SHelen Koike 941cd42f802SHeiko Stuebner static void rkisp1_afm_config_v12(struct rkisp1_params *params, 942cd42f802SHeiko Stuebner const struct rkisp1_cif_isp_afc_config *arg) 943cd42f802SHeiko Stuebner { 944cd42f802SHeiko Stuebner size_t num_of_win = min_t(size_t, ARRAY_SIZE(arg->afm_win), 945cd42f802SHeiko Stuebner arg->num_afm_win); 946cd42f802SHeiko Stuebner u32 afm_ctrl = rkisp1_read(params->rkisp1, RKISP1_CIF_ISP_AFM_CTRL); 947cd42f802SHeiko Stuebner u32 lum_var_shift, afm_var_shift; 948cd42f802SHeiko Stuebner unsigned int i; 949cd42f802SHeiko Stuebner 950cd42f802SHeiko Stuebner /* Switch off to configure. */ 951cd42f802SHeiko Stuebner rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_AFM_CTRL, 952cd42f802SHeiko Stuebner RKISP1_CIF_ISP_AFM_ENA); 953cd42f802SHeiko Stuebner 954cd42f802SHeiko Stuebner for (i = 0; i < num_of_win; i++) { 9550ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_AFM_LT_A + i * 8, 956cd42f802SHeiko Stuebner RKISP1_CIF_ISP_AFM_WINDOW_X(arg->afm_win[i].h_offs) | 9570ef7dc30SLaurent Pinchart RKISP1_CIF_ISP_AFM_WINDOW_Y(arg->afm_win[i].v_offs)); 9580ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_AFM_RB_A + i * 8, 959cd42f802SHeiko Stuebner RKISP1_CIF_ISP_AFM_WINDOW_X(arg->afm_win[i].h_size + 960cd42f802SHeiko Stuebner arg->afm_win[i].h_offs) | 961cd42f802SHeiko Stuebner RKISP1_CIF_ISP_AFM_WINDOW_Y(arg->afm_win[i].v_size + 9620ef7dc30SLaurent Pinchart arg->afm_win[i].v_offs)); 963cd42f802SHeiko Stuebner } 9640ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_AFM_THRES, arg->thres); 965cd42f802SHeiko Stuebner 966cd42f802SHeiko Stuebner lum_var_shift = RKISP1_CIF_ISP_AFM_GET_LUM_SHIFT_a_V12(arg->var_shift); 967cd42f802SHeiko Stuebner afm_var_shift = RKISP1_CIF_ISP_AFM_GET_AFM_SHIFT_a_V12(arg->var_shift); 9680ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_AFM_VAR_SHIFT, 969cd42f802SHeiko Stuebner RKISP1_CIF_ISP_AFM_SET_SHIFT_a_V12(lum_var_shift, afm_var_shift) | 970cd42f802SHeiko Stuebner RKISP1_CIF_ISP_AFM_SET_SHIFT_b_V12(lum_var_shift, afm_var_shift) | 9710ef7dc30SLaurent Pinchart RKISP1_CIF_ISP_AFM_SET_SHIFT_c_V12(lum_var_shift, afm_var_shift)); 972cd42f802SHeiko Stuebner 973cd42f802SHeiko Stuebner /* restore afm status */ 9740ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_AFM_CTRL, afm_ctrl); 975cd42f802SHeiko Stuebner } 976cd42f802SHeiko Stuebner 977e6938cc1SHelen Koike static void rkisp1_ie_config(struct rkisp1_params *params, 978e6938cc1SHelen Koike const struct rkisp1_cif_isp_ie_config *arg) 979e6938cc1SHelen Koike { 980e6938cc1SHelen Koike u32 eff_ctrl; 981e6938cc1SHelen Koike 982e6938cc1SHelen Koike eff_ctrl = rkisp1_read(params->rkisp1, RKISP1_CIF_IMG_EFF_CTRL); 983e6938cc1SHelen Koike eff_ctrl &= ~RKISP1_CIF_IMG_EFF_CTRL_MODE_MASK; 984e6938cc1SHelen Koike 985e6938cc1SHelen Koike if (params->quantization == V4L2_QUANTIZATION_FULL_RANGE) 986e6938cc1SHelen Koike eff_ctrl |= RKISP1_CIF_IMG_EFF_CTRL_YCBCR_FULL; 987e6938cc1SHelen Koike 988e6938cc1SHelen Koike switch (arg->effect) { 989e6938cc1SHelen Koike case V4L2_COLORFX_SEPIA: 990e6938cc1SHelen Koike eff_ctrl |= RKISP1_CIF_IMG_EFF_CTRL_MODE_SEPIA; 991e6938cc1SHelen Koike break; 992e6938cc1SHelen Koike case V4L2_COLORFX_SET_CBCR: 9930ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_IMG_EFF_TINT, 9940ef7dc30SLaurent Pinchart arg->eff_tint); 995e6938cc1SHelen Koike eff_ctrl |= RKISP1_CIF_IMG_EFF_CTRL_MODE_SEPIA; 996e6938cc1SHelen Koike break; 997e6938cc1SHelen Koike /* 998e6938cc1SHelen Koike * Color selection is similar to water color(AQUA): 999e6938cc1SHelen Koike * grayscale + selected color w threshold 1000e6938cc1SHelen Koike */ 1001e6938cc1SHelen Koike case V4L2_COLORFX_AQUA: 1002e6938cc1SHelen Koike eff_ctrl |= RKISP1_CIF_IMG_EFF_CTRL_MODE_COLOR_SEL; 10030ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_IMG_EFF_COLOR_SEL, 10040ef7dc30SLaurent Pinchart arg->color_sel); 1005e6938cc1SHelen Koike break; 1006e6938cc1SHelen Koike case V4L2_COLORFX_EMBOSS: 1007e6938cc1SHelen Koike eff_ctrl |= RKISP1_CIF_IMG_EFF_CTRL_MODE_EMBOSS; 10080ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_IMG_EFF_MAT_1, 10090ef7dc30SLaurent Pinchart arg->eff_mat_1); 10100ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_IMG_EFF_MAT_2, 10110ef7dc30SLaurent Pinchart arg->eff_mat_2); 10120ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_IMG_EFF_MAT_3, 10130ef7dc30SLaurent Pinchart arg->eff_mat_3); 1014e6938cc1SHelen Koike break; 1015e6938cc1SHelen Koike case V4L2_COLORFX_SKETCH: 1016e6938cc1SHelen Koike eff_ctrl |= RKISP1_CIF_IMG_EFF_CTRL_MODE_SKETCH; 10170ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_IMG_EFF_MAT_3, 10180ef7dc30SLaurent Pinchart arg->eff_mat_3); 10190ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_IMG_EFF_MAT_4, 10200ef7dc30SLaurent Pinchart arg->eff_mat_4); 10210ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_IMG_EFF_MAT_5, 10220ef7dc30SLaurent Pinchart arg->eff_mat_5); 1023e6938cc1SHelen Koike break; 1024e6938cc1SHelen Koike case V4L2_COLORFX_BW: 1025e6938cc1SHelen Koike eff_ctrl |= RKISP1_CIF_IMG_EFF_CTRL_MODE_BLACKWHITE; 1026e6938cc1SHelen Koike break; 1027e6938cc1SHelen Koike case V4L2_COLORFX_NEGATIVE: 1028e6938cc1SHelen Koike eff_ctrl |= RKISP1_CIF_IMG_EFF_CTRL_MODE_NEGATIVE; 1029e6938cc1SHelen Koike break; 1030e6938cc1SHelen Koike default: 1031e6938cc1SHelen Koike break; 1032e6938cc1SHelen Koike } 1033e6938cc1SHelen Koike 10340ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_IMG_EFF_CTRL, eff_ctrl); 1035e6938cc1SHelen Koike } 1036e6938cc1SHelen Koike 1037e6938cc1SHelen Koike static void rkisp1_ie_enable(struct rkisp1_params *params, bool en) 1038e6938cc1SHelen Koike { 1039e6938cc1SHelen Koike if (en) { 10403b430c2cSLaurent Pinchart rkisp1_param_set_bits(params, RKISP1_CIF_VI_ICCL, 10413b430c2cSLaurent Pinchart RKISP1_CIF_VI_ICCL_IE_CLK); 10420ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_IMG_EFF_CTRL, 10430ef7dc30SLaurent Pinchart RKISP1_CIF_IMG_EFF_CTRL_ENABLE); 1044e6938cc1SHelen Koike rkisp1_param_set_bits(params, RKISP1_CIF_IMG_EFF_CTRL, 1045e6938cc1SHelen Koike RKISP1_CIF_IMG_EFF_CTRL_CFG_UPD); 1046e6938cc1SHelen Koike } else { 1047e6938cc1SHelen Koike rkisp1_param_clear_bits(params, RKISP1_CIF_IMG_EFF_CTRL, 1048e6938cc1SHelen Koike RKISP1_CIF_IMG_EFF_CTRL_ENABLE); 10493b430c2cSLaurent Pinchart rkisp1_param_clear_bits(params, RKISP1_CIF_VI_ICCL, 10503b430c2cSLaurent Pinchart RKISP1_CIF_VI_ICCL_IE_CLK); 1051e6938cc1SHelen Koike } 1052e6938cc1SHelen Koike } 1053e6938cc1SHelen Koike 1054711d9149SLaurent Pinchart static void rkisp1_csm_config(struct rkisp1_params *params) 1055e6938cc1SHelen Koike { 1056f7aa2d23SLaurent Pinchart struct csm_coeffs { 1057f7aa2d23SLaurent Pinchart u16 limited[9]; 1058f7aa2d23SLaurent Pinchart u16 full[9]; 1059e6938cc1SHelen Koike }; 1060f7aa2d23SLaurent Pinchart static const struct csm_coeffs rec601_coeffs = { 1061f7aa2d23SLaurent Pinchart .limited = { 1062f7aa2d23SLaurent Pinchart 0x0021, 0x0042, 0x000d, 1063e6938cc1SHelen Koike 0x01ed, 0x01db, 0x0038, 1064e6938cc1SHelen Koike 0x0038, 0x01d1, 0x01f7, 1065f7aa2d23SLaurent Pinchart }, 1066f7aa2d23SLaurent Pinchart .full = { 1067f7aa2d23SLaurent Pinchart 0x0026, 0x004b, 0x000f, 1068f7aa2d23SLaurent Pinchart 0x01ea, 0x01d6, 0x0040, 1069f7aa2d23SLaurent Pinchart 0x0040, 0x01ca, 0x01f6, 1070f7aa2d23SLaurent Pinchart }, 1071e6938cc1SHelen Koike }; 1072f7aa2d23SLaurent Pinchart static const struct csm_coeffs rec709_coeffs = { 1073f7aa2d23SLaurent Pinchart .limited = { 1074f7aa2d23SLaurent Pinchart 0x0018, 0x0050, 0x0008, 1075f7aa2d23SLaurent Pinchart 0x01f3, 0x01d5, 0x0038, 1076f7aa2d23SLaurent Pinchart 0x0038, 0x01cd, 0x01fb, 1077f7aa2d23SLaurent Pinchart }, 1078f7aa2d23SLaurent Pinchart .full = { 1079f7aa2d23SLaurent Pinchart 0x001b, 0x005c, 0x0009, 1080f7aa2d23SLaurent Pinchart 0x01f1, 0x01cf, 0x0040, 1081f7aa2d23SLaurent Pinchart 0x0040, 0x01c6, 0x01fa, 1082f7aa2d23SLaurent Pinchart }, 1083f7aa2d23SLaurent Pinchart }; 1084f7aa2d23SLaurent Pinchart static const struct csm_coeffs rec2020_coeffs = { 1085f7aa2d23SLaurent Pinchart .limited = { 1086f7aa2d23SLaurent Pinchart 0x001d, 0x004c, 0x0007, 1087f7aa2d23SLaurent Pinchart 0x01f0, 0x01d8, 0x0038, 1088f7aa2d23SLaurent Pinchart 0x0038, 0x01cd, 0x01fb, 1089f7aa2d23SLaurent Pinchart }, 1090f7aa2d23SLaurent Pinchart .full = { 1091f7aa2d23SLaurent Pinchart 0x0022, 0x0057, 0x0008, 1092f7aa2d23SLaurent Pinchart 0x01ee, 0x01d2, 0x0040, 1093f7aa2d23SLaurent Pinchart 0x0040, 0x01c5, 0x01fb, 1094f7aa2d23SLaurent Pinchart }, 1095f7aa2d23SLaurent Pinchart }; 1096f7aa2d23SLaurent Pinchart static const struct csm_coeffs smpte240m_coeffs = { 1097f7aa2d23SLaurent Pinchart .limited = { 1098f7aa2d23SLaurent Pinchart 0x0018, 0x004f, 0x000a, 1099f7aa2d23SLaurent Pinchart 0x01f3, 0x01d5, 0x0038, 1100f7aa2d23SLaurent Pinchart 0x0038, 0x01ce, 0x01fa, 1101f7aa2d23SLaurent Pinchart }, 1102f7aa2d23SLaurent Pinchart .full = { 1103f7aa2d23SLaurent Pinchart 0x001b, 0x005a, 0x000b, 1104f7aa2d23SLaurent Pinchart 0x01f1, 0x01cf, 0x0040, 1105f7aa2d23SLaurent Pinchart 0x0040, 0x01c7, 0x01f9, 1106f7aa2d23SLaurent Pinchart }, 1107f7aa2d23SLaurent Pinchart }; 1108f7aa2d23SLaurent Pinchart 1109f7aa2d23SLaurent Pinchart const struct csm_coeffs *coeffs; 1110f7aa2d23SLaurent Pinchart const u16 *csm; 1111e6938cc1SHelen Koike unsigned int i; 1112e6938cc1SHelen Koike 1113f7aa2d23SLaurent Pinchart switch (params->ycbcr_encoding) { 1114f7aa2d23SLaurent Pinchart case V4L2_YCBCR_ENC_601: 1115f7aa2d23SLaurent Pinchart default: 1116f7aa2d23SLaurent Pinchart coeffs = &rec601_coeffs; 1117f7aa2d23SLaurent Pinchart break; 1118f7aa2d23SLaurent Pinchart case V4L2_YCBCR_ENC_709: 1119f7aa2d23SLaurent Pinchart coeffs = &rec709_coeffs; 1120f7aa2d23SLaurent Pinchart break; 1121f7aa2d23SLaurent Pinchart case V4L2_YCBCR_ENC_BT2020: 1122f7aa2d23SLaurent Pinchart coeffs = &rec2020_coeffs; 1123f7aa2d23SLaurent Pinchart break; 1124f7aa2d23SLaurent Pinchart case V4L2_YCBCR_ENC_SMPTE240M: 1125f7aa2d23SLaurent Pinchart coeffs = &smpte240m_coeffs; 1126f7aa2d23SLaurent Pinchart break; 1127f7aa2d23SLaurent Pinchart } 1128e6938cc1SHelen Koike 1129f7aa2d23SLaurent Pinchart if (params->quantization == V4L2_QUANTIZATION_FULL_RANGE) { 1130f7aa2d23SLaurent Pinchart csm = coeffs->full; 1131e6938cc1SHelen Koike rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL, 1132e6938cc1SHelen Koike RKISP1_CIF_ISP_CTRL_ISP_CSM_Y_FULL_ENA | 1133e6938cc1SHelen Koike RKISP1_CIF_ISP_CTRL_ISP_CSM_C_FULL_ENA); 1134e6938cc1SHelen Koike } else { 1135f7aa2d23SLaurent Pinchart csm = coeffs->limited; 1136e6938cc1SHelen Koike rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_CTRL, 1137e6938cc1SHelen Koike RKISP1_CIF_ISP_CTRL_ISP_CSM_Y_FULL_ENA | 1138e6938cc1SHelen Koike RKISP1_CIF_ISP_CTRL_ISP_CSM_C_FULL_ENA); 1139e6938cc1SHelen Koike } 1140f7aa2d23SLaurent Pinchart 1141f7aa2d23SLaurent Pinchart for (i = 0; i < 9; i++) 1142f7aa2d23SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_CC_COEFF_0 + i * 4, 1143f7aa2d23SLaurent Pinchart csm[i]); 1144e6938cc1SHelen Koike } 1145e6938cc1SHelen Koike 1146e6938cc1SHelen Koike /* ISP De-noise Pre-Filter(DPF) function */ 1147e6938cc1SHelen Koike static void rkisp1_dpf_config(struct rkisp1_params *params, 1148e6938cc1SHelen Koike const struct rkisp1_cif_isp_dpf_config *arg) 1149e6938cc1SHelen Koike { 1150e6938cc1SHelen Koike unsigned int isp_dpf_mode, spatial_coeff, i; 1151e6938cc1SHelen Koike 1152e6938cc1SHelen Koike switch (arg->gain.mode) { 1153e6938cc1SHelen Koike case RKISP1_CIF_ISP_DPF_GAIN_USAGE_NF_GAINS: 1154e6938cc1SHelen Koike isp_dpf_mode = RKISP1_CIF_ISP_DPF_MODE_USE_NF_GAIN | 1155e6938cc1SHelen Koike RKISP1_CIF_ISP_DPF_MODE_AWB_GAIN_COMP; 1156e6938cc1SHelen Koike break; 1157e6938cc1SHelen Koike case RKISP1_CIF_ISP_DPF_GAIN_USAGE_LSC_GAINS: 1158e6938cc1SHelen Koike isp_dpf_mode = RKISP1_CIF_ISP_DPF_MODE_LSC_GAIN_COMP; 1159e6938cc1SHelen Koike break; 1160e6938cc1SHelen Koike case RKISP1_CIF_ISP_DPF_GAIN_USAGE_NF_LSC_GAINS: 1161e6938cc1SHelen Koike isp_dpf_mode = RKISP1_CIF_ISP_DPF_MODE_USE_NF_GAIN | 1162e6938cc1SHelen Koike RKISP1_CIF_ISP_DPF_MODE_AWB_GAIN_COMP | 1163e6938cc1SHelen Koike RKISP1_CIF_ISP_DPF_MODE_LSC_GAIN_COMP; 1164e6938cc1SHelen Koike break; 1165e6938cc1SHelen Koike case RKISP1_CIF_ISP_DPF_GAIN_USAGE_AWB_GAINS: 1166e6938cc1SHelen Koike isp_dpf_mode = RKISP1_CIF_ISP_DPF_MODE_AWB_GAIN_COMP; 1167e6938cc1SHelen Koike break; 1168e6938cc1SHelen Koike case RKISP1_CIF_ISP_DPF_GAIN_USAGE_AWB_LSC_GAINS: 1169e6938cc1SHelen Koike isp_dpf_mode = RKISP1_CIF_ISP_DPF_MODE_LSC_GAIN_COMP | 1170e6938cc1SHelen Koike RKISP1_CIF_ISP_DPF_MODE_AWB_GAIN_COMP; 1171e6938cc1SHelen Koike break; 1172e6938cc1SHelen Koike case RKISP1_CIF_ISP_DPF_GAIN_USAGE_DISABLED: 1173e6938cc1SHelen Koike default: 1174e6938cc1SHelen Koike isp_dpf_mode = 0; 1175e6938cc1SHelen Koike break; 1176e6938cc1SHelen Koike } 1177e6938cc1SHelen Koike 1178e6938cc1SHelen Koike if (arg->nll.scale_mode == RKISP1_CIF_ISP_NLL_SCALE_LOGARITHMIC) 1179e6938cc1SHelen Koike isp_dpf_mode |= RKISP1_CIF_ISP_DPF_MODE_NLL_SEGMENTATION; 1180e6938cc1SHelen Koike if (arg->rb_flt.fltsize == RKISP1_CIF_ISP_DPF_RB_FILTERSIZE_9x9) 1181e6938cc1SHelen Koike isp_dpf_mode |= RKISP1_CIF_ISP_DPF_MODE_RB_FLTSIZE_9x9; 1182e6938cc1SHelen Koike if (!arg->rb_flt.r_enable) 1183e6938cc1SHelen Koike isp_dpf_mode |= RKISP1_CIF_ISP_DPF_MODE_R_FLT_DIS; 1184e6938cc1SHelen Koike if (!arg->rb_flt.b_enable) 1185e6938cc1SHelen Koike isp_dpf_mode |= RKISP1_CIF_ISP_DPF_MODE_B_FLT_DIS; 1186e6938cc1SHelen Koike if (!arg->g_flt.gb_enable) 1187e6938cc1SHelen Koike isp_dpf_mode |= RKISP1_CIF_ISP_DPF_MODE_GB_FLT_DIS; 1188e6938cc1SHelen Koike if (!arg->g_flt.gr_enable) 1189e6938cc1SHelen Koike isp_dpf_mode |= RKISP1_CIF_ISP_DPF_MODE_GR_FLT_DIS; 1190e6938cc1SHelen Koike 1191e6938cc1SHelen Koike rkisp1_param_set_bits(params, RKISP1_CIF_ISP_DPF_MODE, 1192e6938cc1SHelen Koike isp_dpf_mode); 11930ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_DPF_NF_GAIN_B, 11940ef7dc30SLaurent Pinchart arg->gain.nf_b_gain); 11950ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_DPF_NF_GAIN_R, 11960ef7dc30SLaurent Pinchart arg->gain.nf_r_gain); 11970ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_DPF_NF_GAIN_GB, 11980ef7dc30SLaurent Pinchart arg->gain.nf_gb_gain); 11990ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_DPF_NF_GAIN_GR, 12000ef7dc30SLaurent Pinchart arg->gain.nf_gr_gain); 1201e6938cc1SHelen Koike 1202e6938cc1SHelen Koike for (i = 0; i < RKISP1_CIF_ISP_DPF_MAX_NLF_COEFFS; i++) { 12030ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, 12040ef7dc30SLaurent Pinchart RKISP1_CIF_ISP_DPF_NULL_COEFF_0 + i * 4, 12050ef7dc30SLaurent Pinchart arg->nll.coeff[i]); 1206e6938cc1SHelen Koike } 1207e6938cc1SHelen Koike 1208e6938cc1SHelen Koike spatial_coeff = arg->g_flt.spatial_coeff[0] | 1209e6938cc1SHelen Koike (arg->g_flt.spatial_coeff[1] << 8) | 1210e6938cc1SHelen Koike (arg->g_flt.spatial_coeff[2] << 16) | 1211e6938cc1SHelen Koike (arg->g_flt.spatial_coeff[3] << 24); 12120ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_DPF_S_WEIGHT_G_1_4, 12130ef7dc30SLaurent Pinchart spatial_coeff); 1214e6938cc1SHelen Koike 1215e6938cc1SHelen Koike spatial_coeff = arg->g_flt.spatial_coeff[4] | 1216e6938cc1SHelen Koike (arg->g_flt.spatial_coeff[5] << 8); 12170ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_DPF_S_WEIGHT_G_5_6, 12180ef7dc30SLaurent Pinchart spatial_coeff); 1219e6938cc1SHelen Koike 1220e6938cc1SHelen Koike spatial_coeff = arg->rb_flt.spatial_coeff[0] | 1221e6938cc1SHelen Koike (arg->rb_flt.spatial_coeff[1] << 8) | 1222e6938cc1SHelen Koike (arg->rb_flt.spatial_coeff[2] << 16) | 1223e6938cc1SHelen Koike (arg->rb_flt.spatial_coeff[3] << 24); 12240ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_DPF_S_WEIGHT_RB_1_4, 12250ef7dc30SLaurent Pinchart spatial_coeff); 1226e6938cc1SHelen Koike 1227e6938cc1SHelen Koike spatial_coeff = arg->rb_flt.spatial_coeff[4] | 1228e6938cc1SHelen Koike (arg->rb_flt.spatial_coeff[5] << 8); 12290ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_DPF_S_WEIGHT_RB_5_6, 12300ef7dc30SLaurent Pinchart spatial_coeff); 1231e6938cc1SHelen Koike } 1232e6938cc1SHelen Koike 1233e6938cc1SHelen Koike static void 1234e6938cc1SHelen Koike rkisp1_dpf_strength_config(struct rkisp1_params *params, 1235e6938cc1SHelen Koike const struct rkisp1_cif_isp_dpf_strength_config *arg) 1236e6938cc1SHelen Koike { 12370ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_DPF_STRENGTH_B, arg->b); 12380ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_DPF_STRENGTH_G, arg->g); 12390ef7dc30SLaurent Pinchart rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_DPF_STRENGTH_R, arg->r); 1240e6938cc1SHelen Koike } 1241e6938cc1SHelen Koike 1242e6938cc1SHelen Koike static void 1243e6938cc1SHelen Koike rkisp1_isp_isr_other_config(struct rkisp1_params *params, 1244e6938cc1SHelen Koike const struct rkisp1_params_cfg *new_params) 1245e6938cc1SHelen Koike { 1246e6938cc1SHelen Koike unsigned int module_en_update, module_cfg_update, module_ens; 1247e6938cc1SHelen Koike 1248e6938cc1SHelen Koike module_en_update = new_params->module_en_update; 1249e6938cc1SHelen Koike module_cfg_update = new_params->module_cfg_update; 1250e6938cc1SHelen Koike module_ens = new_params->module_ens; 1251e6938cc1SHelen Koike 1252e6938cc1SHelen Koike /* update dpc config */ 1253e6938cc1SHelen Koike if (module_cfg_update & RKISP1_CIF_ISP_MODULE_DPCC) 1254e6938cc1SHelen Koike rkisp1_dpcc_config(params, 1255e6938cc1SHelen Koike &new_params->others.dpcc_config); 1256e6938cc1SHelen Koike 1257e6938cc1SHelen Koike if (module_en_update & RKISP1_CIF_ISP_MODULE_DPCC) { 1258e6938cc1SHelen Koike if (module_ens & RKISP1_CIF_ISP_MODULE_DPCC) 1259e6938cc1SHelen Koike rkisp1_param_set_bits(params, 1260e6938cc1SHelen Koike RKISP1_CIF_ISP_DPCC_MODE, 12619daa2b84SLaurent Pinchart RKISP1_CIF_ISP_DPCC_MODE_DPCC_ENABLE); 1262e6938cc1SHelen Koike else 1263e6938cc1SHelen Koike rkisp1_param_clear_bits(params, 1264e6938cc1SHelen Koike RKISP1_CIF_ISP_DPCC_MODE, 12659daa2b84SLaurent Pinchart RKISP1_CIF_ISP_DPCC_MODE_DPCC_ENABLE); 1266e6938cc1SHelen Koike } 1267e6938cc1SHelen Koike 1268e6938cc1SHelen Koike /* update bls config */ 1269e6938cc1SHelen Koike if (module_cfg_update & RKISP1_CIF_ISP_MODULE_BLS) 1270e6938cc1SHelen Koike rkisp1_bls_config(params, 1271e6938cc1SHelen Koike &new_params->others.bls_config); 1272e6938cc1SHelen Koike 1273e6938cc1SHelen Koike if (module_en_update & RKISP1_CIF_ISP_MODULE_BLS) { 1274e6938cc1SHelen Koike if (module_ens & RKISP1_CIF_ISP_MODULE_BLS) 1275e6938cc1SHelen Koike rkisp1_param_set_bits(params, 1276e6938cc1SHelen Koike RKISP1_CIF_ISP_BLS_CTRL, 1277e6938cc1SHelen Koike RKISP1_CIF_ISP_BLS_ENA); 1278e6938cc1SHelen Koike else 1279e6938cc1SHelen Koike rkisp1_param_clear_bits(params, 1280e6938cc1SHelen Koike RKISP1_CIF_ISP_BLS_CTRL, 1281e6938cc1SHelen Koike RKISP1_CIF_ISP_BLS_ENA); 1282e6938cc1SHelen Koike } 1283e6938cc1SHelen Koike 1284e6938cc1SHelen Koike /* update sdg config */ 1285e6938cc1SHelen Koike if (module_cfg_update & RKISP1_CIF_ISP_MODULE_SDG) 1286e6938cc1SHelen Koike rkisp1_sdg_config(params, 1287e6938cc1SHelen Koike &new_params->others.sdg_config); 1288e6938cc1SHelen Koike 1289e6938cc1SHelen Koike if (module_en_update & RKISP1_CIF_ISP_MODULE_SDG) { 1290e6938cc1SHelen Koike if (module_ens & RKISP1_CIF_ISP_MODULE_SDG) 1291e6938cc1SHelen Koike rkisp1_param_set_bits(params, 1292e6938cc1SHelen Koike RKISP1_CIF_ISP_CTRL, 1293e6938cc1SHelen Koike RKISP1_CIF_ISP_CTRL_ISP_GAMMA_IN_ENA); 1294e6938cc1SHelen Koike else 1295e6938cc1SHelen Koike rkisp1_param_clear_bits(params, 1296e6938cc1SHelen Koike RKISP1_CIF_ISP_CTRL, 1297e6938cc1SHelen Koike RKISP1_CIF_ISP_CTRL_ISP_GAMMA_IN_ENA); 1298e6938cc1SHelen Koike } 1299e6938cc1SHelen Koike 1300e6938cc1SHelen Koike /* update lsc config */ 1301e6938cc1SHelen Koike if (module_cfg_update & RKISP1_CIF_ISP_MODULE_LSC) 1302e6938cc1SHelen Koike rkisp1_lsc_config(params, 1303e6938cc1SHelen Koike &new_params->others.lsc_config); 1304e6938cc1SHelen Koike 1305e6938cc1SHelen Koike if (module_en_update & RKISP1_CIF_ISP_MODULE_LSC) { 1306e6938cc1SHelen Koike if (module_ens & RKISP1_CIF_ISP_MODULE_LSC) 1307e6938cc1SHelen Koike rkisp1_param_set_bits(params, 1308e6938cc1SHelen Koike RKISP1_CIF_ISP_LSC_CTRL, 1309e6938cc1SHelen Koike RKISP1_CIF_ISP_LSC_CTRL_ENA); 1310e6938cc1SHelen Koike else 1311e6938cc1SHelen Koike rkisp1_param_clear_bits(params, 1312e6938cc1SHelen Koike RKISP1_CIF_ISP_LSC_CTRL, 1313e6938cc1SHelen Koike RKISP1_CIF_ISP_LSC_CTRL_ENA); 1314e6938cc1SHelen Koike } 1315e6938cc1SHelen Koike 1316e6938cc1SHelen Koike /* update awb gains */ 1317e6938cc1SHelen Koike if (module_cfg_update & RKISP1_CIF_ISP_MODULE_AWB_GAIN) 13185e8d9d72SHeiko Stuebner params->ops->awb_gain_config(params, &new_params->others.awb_gain_config); 1319e6938cc1SHelen Koike 1320e6938cc1SHelen Koike if (module_en_update & RKISP1_CIF_ISP_MODULE_AWB_GAIN) { 1321e6938cc1SHelen Koike if (module_ens & RKISP1_CIF_ISP_MODULE_AWB_GAIN) 1322e6938cc1SHelen Koike rkisp1_param_set_bits(params, 1323e6938cc1SHelen Koike RKISP1_CIF_ISP_CTRL, 1324e6938cc1SHelen Koike RKISP1_CIF_ISP_CTRL_ISP_AWB_ENA); 1325e6938cc1SHelen Koike else 1326e6938cc1SHelen Koike rkisp1_param_clear_bits(params, 1327e6938cc1SHelen Koike RKISP1_CIF_ISP_CTRL, 1328e6938cc1SHelen Koike RKISP1_CIF_ISP_CTRL_ISP_AWB_ENA); 1329e6938cc1SHelen Koike } 1330e6938cc1SHelen Koike 1331e6938cc1SHelen Koike /* update bdm config */ 1332e6938cc1SHelen Koike if (module_cfg_update & RKISP1_CIF_ISP_MODULE_BDM) 1333e6938cc1SHelen Koike rkisp1_bdm_config(params, 1334e6938cc1SHelen Koike &new_params->others.bdm_config); 1335e6938cc1SHelen Koike 1336e6938cc1SHelen Koike if (module_en_update & RKISP1_CIF_ISP_MODULE_BDM) { 1337e6938cc1SHelen Koike if (module_ens & RKISP1_CIF_ISP_MODULE_BDM) 1338e6938cc1SHelen Koike rkisp1_param_set_bits(params, 1339e6938cc1SHelen Koike RKISP1_CIF_ISP_DEMOSAIC, 1340e6938cc1SHelen Koike RKISP1_CIF_ISP_DEMOSAIC_BYPASS); 1341e6938cc1SHelen Koike else 1342e6938cc1SHelen Koike rkisp1_param_clear_bits(params, 1343e6938cc1SHelen Koike RKISP1_CIF_ISP_DEMOSAIC, 1344e6938cc1SHelen Koike RKISP1_CIF_ISP_DEMOSAIC_BYPASS); 1345e6938cc1SHelen Koike } 1346e6938cc1SHelen Koike 1347e6938cc1SHelen Koike /* update filter config */ 1348e6938cc1SHelen Koike if (module_cfg_update & RKISP1_CIF_ISP_MODULE_FLT) 1349e6938cc1SHelen Koike rkisp1_flt_config(params, 1350e6938cc1SHelen Koike &new_params->others.flt_config); 1351e6938cc1SHelen Koike 1352e6938cc1SHelen Koike if (module_en_update & RKISP1_CIF_ISP_MODULE_FLT) { 1353e6938cc1SHelen Koike if (module_ens & RKISP1_CIF_ISP_MODULE_FLT) 1354e6938cc1SHelen Koike rkisp1_param_set_bits(params, 1355e6938cc1SHelen Koike RKISP1_CIF_ISP_FILT_MODE, 1356e6938cc1SHelen Koike RKISP1_CIF_ISP_FLT_ENA); 1357e6938cc1SHelen Koike else 1358e6938cc1SHelen Koike rkisp1_param_clear_bits(params, 1359e6938cc1SHelen Koike RKISP1_CIF_ISP_FILT_MODE, 1360e6938cc1SHelen Koike RKISP1_CIF_ISP_FLT_ENA); 1361e6938cc1SHelen Koike } 1362e6938cc1SHelen Koike 1363e6938cc1SHelen Koike /* update ctk config */ 1364e6938cc1SHelen Koike if (module_cfg_update & RKISP1_CIF_ISP_MODULE_CTK) 1365e6938cc1SHelen Koike rkisp1_ctk_config(params, 1366e6938cc1SHelen Koike &new_params->others.ctk_config); 1367e6938cc1SHelen Koike 1368e6938cc1SHelen Koike if (module_en_update & RKISP1_CIF_ISP_MODULE_CTK) 136918a4ca76SDafna Hirschfeld rkisp1_ctk_enable(params, !!(module_ens & RKISP1_CIF_ISP_MODULE_CTK)); 1370e6938cc1SHelen Koike 1371e6938cc1SHelen Koike /* update goc config */ 1372e6938cc1SHelen Koike if (module_cfg_update & RKISP1_CIF_ISP_MODULE_GOC) 13735e8d9d72SHeiko Stuebner params->ops->goc_config(params, &new_params->others.goc_config); 1374e6938cc1SHelen Koike 1375e6938cc1SHelen Koike if (module_en_update & RKISP1_CIF_ISP_MODULE_GOC) { 1376e6938cc1SHelen Koike if (module_ens & RKISP1_CIF_ISP_MODULE_GOC) 1377e6938cc1SHelen Koike rkisp1_param_set_bits(params, 1378e6938cc1SHelen Koike RKISP1_CIF_ISP_CTRL, 1379e6938cc1SHelen Koike RKISP1_CIF_ISP_CTRL_ISP_GAMMA_OUT_ENA); 1380e6938cc1SHelen Koike else 1381e6938cc1SHelen Koike rkisp1_param_clear_bits(params, 1382e6938cc1SHelen Koike RKISP1_CIF_ISP_CTRL, 1383e6938cc1SHelen Koike RKISP1_CIF_ISP_CTRL_ISP_GAMMA_OUT_ENA); 1384e6938cc1SHelen Koike } 1385e6938cc1SHelen Koike 1386e6938cc1SHelen Koike /* update cproc config */ 138718a4ca76SDafna Hirschfeld if (module_cfg_update & RKISP1_CIF_ISP_MODULE_CPROC) 1388e6938cc1SHelen Koike rkisp1_cproc_config(params, 1389e6938cc1SHelen Koike &new_params->others.cproc_config); 1390e6938cc1SHelen Koike 1391e6938cc1SHelen Koike if (module_en_update & RKISP1_CIF_ISP_MODULE_CPROC) { 1392e6938cc1SHelen Koike if (module_ens & RKISP1_CIF_ISP_MODULE_CPROC) 1393e6938cc1SHelen Koike rkisp1_param_set_bits(params, 1394e6938cc1SHelen Koike RKISP1_CIF_C_PROC_CTRL, 1395e6938cc1SHelen Koike RKISP1_CIF_C_PROC_CTR_ENABLE); 1396e6938cc1SHelen Koike else 1397e6938cc1SHelen Koike rkisp1_param_clear_bits(params, 1398e6938cc1SHelen Koike RKISP1_CIF_C_PROC_CTRL, 1399e6938cc1SHelen Koike RKISP1_CIF_C_PROC_CTR_ENABLE); 1400e6938cc1SHelen Koike } 1401e6938cc1SHelen Koike 1402e6938cc1SHelen Koike /* update ie config */ 1403e6938cc1SHelen Koike if (module_cfg_update & RKISP1_CIF_ISP_MODULE_IE) 140418a4ca76SDafna Hirschfeld rkisp1_ie_config(params, &new_params->others.ie_config); 1405e6938cc1SHelen Koike 1406e6938cc1SHelen Koike if (module_en_update & RKISP1_CIF_ISP_MODULE_IE) 140718a4ca76SDafna Hirschfeld rkisp1_ie_enable(params, !!(module_ens & RKISP1_CIF_ISP_MODULE_IE)); 1408e6938cc1SHelen Koike 1409e6938cc1SHelen Koike /* update dpf config */ 1410e6938cc1SHelen Koike if (module_cfg_update & RKISP1_CIF_ISP_MODULE_DPF) 141118a4ca76SDafna Hirschfeld rkisp1_dpf_config(params, &new_params->others.dpf_config); 1412e6938cc1SHelen Koike 1413e6938cc1SHelen Koike if (module_en_update & RKISP1_CIF_ISP_MODULE_DPF) { 1414e6938cc1SHelen Koike if (module_ens & RKISP1_CIF_ISP_MODULE_DPF) 1415e6938cc1SHelen Koike rkisp1_param_set_bits(params, 1416e6938cc1SHelen Koike RKISP1_CIF_ISP_DPF_MODE, 1417e6938cc1SHelen Koike RKISP1_CIF_ISP_DPF_MODE_EN); 1418e6938cc1SHelen Koike else 1419e6938cc1SHelen Koike rkisp1_param_clear_bits(params, 1420e6938cc1SHelen Koike RKISP1_CIF_ISP_DPF_MODE, 1421e6938cc1SHelen Koike RKISP1_CIF_ISP_DPF_MODE_EN); 1422e6938cc1SHelen Koike } 1423e6938cc1SHelen Koike 1424e6938cc1SHelen Koike if ((module_en_update & RKISP1_CIF_ISP_MODULE_DPF_STRENGTH) || 1425e6938cc1SHelen Koike (module_cfg_update & RKISP1_CIF_ISP_MODULE_DPF_STRENGTH)) { 1426e6938cc1SHelen Koike /* update dpf strength config */ 1427e6938cc1SHelen Koike rkisp1_dpf_strength_config(params, 1428e6938cc1SHelen Koike &new_params->others.dpf_strength_config); 1429e6938cc1SHelen Koike } 1430e6938cc1SHelen Koike } 1431e6938cc1SHelen Koike 1432e6938cc1SHelen Koike static void rkisp1_isp_isr_meas_config(struct rkisp1_params *params, 1433e6938cc1SHelen Koike struct rkisp1_params_cfg *new_params) 1434e6938cc1SHelen Koike { 1435e6938cc1SHelen Koike unsigned int module_en_update, module_cfg_update, module_ens; 1436e6938cc1SHelen Koike 1437e6938cc1SHelen Koike module_en_update = new_params->module_en_update; 1438e6938cc1SHelen Koike module_cfg_update = new_params->module_cfg_update; 1439e6938cc1SHelen Koike module_ens = new_params->module_ens; 1440e6938cc1SHelen Koike 1441e6938cc1SHelen Koike /* update awb config */ 1442e6938cc1SHelen Koike if (module_cfg_update & RKISP1_CIF_ISP_MODULE_AWB) 14435e8d9d72SHeiko Stuebner params->ops->awb_meas_config(params, &new_params->meas.awb_meas_config); 1444e6938cc1SHelen Koike 1445e6938cc1SHelen Koike if (module_en_update & RKISP1_CIF_ISP_MODULE_AWB) 14465e8d9d72SHeiko Stuebner params->ops->awb_meas_enable(params, 1447e6938cc1SHelen Koike &new_params->meas.awb_meas_config, 1448e6938cc1SHelen Koike !!(module_ens & RKISP1_CIF_ISP_MODULE_AWB)); 1449e6938cc1SHelen Koike 1450e6938cc1SHelen Koike /* update afc config */ 1451e6938cc1SHelen Koike if (module_cfg_update & RKISP1_CIF_ISP_MODULE_AFC) 14525e8d9d72SHeiko Stuebner params->ops->afm_config(params, 1453e6938cc1SHelen Koike &new_params->meas.afc_config); 1454e6938cc1SHelen Koike 1455e6938cc1SHelen Koike if (module_en_update & RKISP1_CIF_ISP_MODULE_AFC) { 1456e6938cc1SHelen Koike if (module_ens & RKISP1_CIF_ISP_MODULE_AFC) 1457e6938cc1SHelen Koike rkisp1_param_set_bits(params, 1458e6938cc1SHelen Koike RKISP1_CIF_ISP_AFM_CTRL, 1459e6938cc1SHelen Koike RKISP1_CIF_ISP_AFM_ENA); 1460e6938cc1SHelen Koike else 1461e6938cc1SHelen Koike rkisp1_param_clear_bits(params, 1462e6938cc1SHelen Koike RKISP1_CIF_ISP_AFM_CTRL, 1463e6938cc1SHelen Koike RKISP1_CIF_ISP_AFM_ENA); 1464e6938cc1SHelen Koike } 1465e6938cc1SHelen Koike 1466e6938cc1SHelen Koike /* update hst config */ 1467e6938cc1SHelen Koike if (module_cfg_update & RKISP1_CIF_ISP_MODULE_HST) 14685e8d9d72SHeiko Stuebner params->ops->hst_config(params, 1469e6938cc1SHelen Koike &new_params->meas.hst_config); 1470e6938cc1SHelen Koike 1471e6938cc1SHelen Koike if (module_en_update & RKISP1_CIF_ISP_MODULE_HST) 14725e8d9d72SHeiko Stuebner params->ops->hst_enable(params, 1473e6938cc1SHelen Koike &new_params->meas.hst_config, 1474e6938cc1SHelen Koike !!(module_ens & RKISP1_CIF_ISP_MODULE_HST)); 1475e6938cc1SHelen Koike 1476e6938cc1SHelen Koike /* update aec config */ 1477e6938cc1SHelen Koike if (module_cfg_update & RKISP1_CIF_ISP_MODULE_AEC) 14785e8d9d72SHeiko Stuebner params->ops->aec_config(params, 1479e6938cc1SHelen Koike &new_params->meas.aec_config); 1480e6938cc1SHelen Koike 1481e6938cc1SHelen Koike if (module_en_update & RKISP1_CIF_ISP_MODULE_AEC) { 1482e6938cc1SHelen Koike if (module_ens & RKISP1_CIF_ISP_MODULE_AEC) 1483e6938cc1SHelen Koike rkisp1_param_set_bits(params, 1484e6938cc1SHelen Koike RKISP1_CIF_ISP_EXP_CTRL, 1485e6938cc1SHelen Koike RKISP1_CIF_ISP_EXP_ENA); 1486e6938cc1SHelen Koike else 1487e6938cc1SHelen Koike rkisp1_param_clear_bits(params, 1488e6938cc1SHelen Koike RKISP1_CIF_ISP_EXP_CTRL, 1489e6938cc1SHelen Koike RKISP1_CIF_ISP_EXP_ENA); 1490e6938cc1SHelen Koike } 1491e6938cc1SHelen Koike } 1492e6938cc1SHelen Koike 1493e6938cc1SHelen Koike static void rkisp1_params_apply_params_cfg(struct rkisp1_params *params, 1494e6938cc1SHelen Koike unsigned int frame_sequence) 1495e6938cc1SHelen Koike { 1496e6938cc1SHelen Koike struct rkisp1_params_cfg *new_params; 1497e6938cc1SHelen Koike struct rkisp1_buffer *cur_buf = NULL; 1498e6938cc1SHelen Koike 1499e6938cc1SHelen Koike if (list_empty(¶ms->params)) 1500e6938cc1SHelen Koike return; 1501e6938cc1SHelen Koike 1502e6938cc1SHelen Koike cur_buf = list_first_entry(¶ms->params, 1503e6938cc1SHelen Koike struct rkisp1_buffer, queue); 1504e6938cc1SHelen Koike 150507e59d91SDafna Hirschfeld new_params = (struct rkisp1_params_cfg *)vb2_plane_vaddr(&cur_buf->vb.vb2_buf, 0); 1506e6938cc1SHelen Koike 1507e6938cc1SHelen Koike rkisp1_isp_isr_other_config(params, new_params); 1508e6938cc1SHelen Koike rkisp1_isp_isr_meas_config(params, new_params); 1509e6938cc1SHelen Koike 1510e6938cc1SHelen Koike /* update shadow register immediately */ 1511e6938cc1SHelen Koike rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL, RKISP1_CIF_ISP_CTRL_ISP_CFG_UPD); 1512e6938cc1SHelen Koike 1513e6938cc1SHelen Koike list_del(&cur_buf->queue); 1514e6938cc1SHelen Koike 1515e6938cc1SHelen Koike cur_buf->vb.sequence = frame_sequence; 1516e6938cc1SHelen Koike vb2_buffer_done(&cur_buf->vb.vb2_buf, VB2_BUF_STATE_DONE); 1517e6938cc1SHelen Koike } 1518e6938cc1SHelen Koike 1519e6938cc1SHelen Koike void rkisp1_params_isr(struct rkisp1_device *rkisp1) 1520e6938cc1SHelen Koike { 1521e6938cc1SHelen Koike /* 1522e6938cc1SHelen Koike * This isr is called when the ISR finishes processing a frame (RKISP1_CIF_ISP_FRAME). 1523e6938cc1SHelen Koike * Configurations performed here will be applied on the next frame. 1524e6938cc1SHelen Koike * Since frame_sequence is updated on the vertical sync signal, we should use 1525e6938cc1SHelen Koike * frame_sequence + 1 here to indicate to userspace on which frame these parameters 1526e6938cc1SHelen Koike * are being applied. 1527e6938cc1SHelen Koike */ 1528e6938cc1SHelen Koike unsigned int frame_sequence = rkisp1->isp.frame_sequence + 1; 1529e6938cc1SHelen Koike struct rkisp1_params *params = &rkisp1->params; 1530e6938cc1SHelen Koike 1531e6938cc1SHelen Koike spin_lock(¶ms->config_lock); 1532e6938cc1SHelen Koike rkisp1_params_apply_params_cfg(params, frame_sequence); 1533e6938cc1SHelen Koike 1534e6938cc1SHelen Koike spin_unlock(¶ms->config_lock); 1535e6938cc1SHelen Koike } 1536e6938cc1SHelen Koike 1537e6938cc1SHelen Koike static const struct rkisp1_cif_isp_awb_meas_config rkisp1_awb_params_default_config = { 1538e6938cc1SHelen Koike { 1539e6938cc1SHelen Koike 0, 0, RKISP1_DEFAULT_WIDTH, RKISP1_DEFAULT_HEIGHT 1540e6938cc1SHelen Koike }, 1541e6938cc1SHelen Koike RKISP1_CIF_ISP_AWB_MODE_YCBCR, 200, 30, 20, 20, 0, 128, 128 1542e6938cc1SHelen Koike }; 1543e6938cc1SHelen Koike 1544e6938cc1SHelen Koike static const struct rkisp1_cif_isp_aec_config rkisp1_aec_params_default_config = { 1545e6938cc1SHelen Koike RKISP1_CIF_ISP_EXP_MEASURING_MODE_0, 1546e6938cc1SHelen Koike RKISP1_CIF_ISP_EXP_CTRL_AUTOSTOP_0, 1547e6938cc1SHelen Koike { 1548e6938cc1SHelen Koike RKISP1_DEFAULT_WIDTH >> 2, RKISP1_DEFAULT_HEIGHT >> 2, 1549e6938cc1SHelen Koike RKISP1_DEFAULT_WIDTH >> 1, RKISP1_DEFAULT_HEIGHT >> 1 1550e6938cc1SHelen Koike } 1551e6938cc1SHelen Koike }; 1552e6938cc1SHelen Koike 1553e6938cc1SHelen Koike static const struct rkisp1_cif_isp_hst_config rkisp1_hst_params_default_config = { 1554e6938cc1SHelen Koike RKISP1_CIF_ISP_HISTOGRAM_MODE_RGB_COMBINED, 1555e6938cc1SHelen Koike 3, 1556e6938cc1SHelen Koike { 1557e6938cc1SHelen Koike RKISP1_DEFAULT_WIDTH >> 2, RKISP1_DEFAULT_HEIGHT >> 2, 1558e6938cc1SHelen Koike RKISP1_DEFAULT_WIDTH >> 1, RKISP1_DEFAULT_HEIGHT >> 1 1559e6938cc1SHelen Koike }, 1560e6938cc1SHelen Koike { 1561e6938cc1SHelen Koike 0, /* To be filled in with 0x01 at runtime. */ 1562e6938cc1SHelen Koike } 1563e6938cc1SHelen Koike }; 1564e6938cc1SHelen Koike 1565e6938cc1SHelen Koike static const struct rkisp1_cif_isp_afc_config rkisp1_afc_params_default_config = { 1566e6938cc1SHelen Koike 1, 1567e6938cc1SHelen Koike { 1568e6938cc1SHelen Koike { 1569e6938cc1SHelen Koike 300, 225, 200, 150 1570e6938cc1SHelen Koike } 1571e6938cc1SHelen Koike }, 1572e6938cc1SHelen Koike 4, 1573e6938cc1SHelen Koike 14 1574e6938cc1SHelen Koike }; 1575e6938cc1SHelen Koike 1576e6938cc1SHelen Koike static void rkisp1_params_config_parameter(struct rkisp1_params *params) 1577e6938cc1SHelen Koike { 1578e6938cc1SHelen Koike struct rkisp1_cif_isp_hst_config hst = rkisp1_hst_params_default_config; 1579e6938cc1SHelen Koike 15805e8d9d72SHeiko Stuebner params->ops->awb_meas_config(params, &rkisp1_awb_params_default_config); 15815e8d9d72SHeiko Stuebner params->ops->awb_meas_enable(params, &rkisp1_awb_params_default_config, 1582e6938cc1SHelen Koike true); 1583e6938cc1SHelen Koike 15845e8d9d72SHeiko Stuebner params->ops->aec_config(params, &rkisp1_aec_params_default_config); 1585e6938cc1SHelen Koike rkisp1_param_set_bits(params, RKISP1_CIF_ISP_EXP_CTRL, 1586e6938cc1SHelen Koike RKISP1_CIF_ISP_EXP_ENA); 1587e6938cc1SHelen Koike 15885e8d9d72SHeiko Stuebner params->ops->afm_config(params, &rkisp1_afc_params_default_config); 1589e6938cc1SHelen Koike rkisp1_param_set_bits(params, RKISP1_CIF_ISP_AFM_CTRL, 1590e6938cc1SHelen Koike RKISP1_CIF_ISP_AFM_ENA); 1591e6938cc1SHelen Koike 1592e6938cc1SHelen Koike memset(hst.hist_weight, 0x01, sizeof(hst.hist_weight)); 15935e8d9d72SHeiko Stuebner params->ops->hst_config(params, &hst); 1594dce8ccb2SHeiko Stuebner rkisp1_param_set_bits(params, RKISP1_CIF_ISP_HIST_PROP_V10, 1595e6938cc1SHelen Koike rkisp1_hst_params_default_config.mode); 1596e6938cc1SHelen Koike 1597711d9149SLaurent Pinchart rkisp1_csm_config(params); 1598e6938cc1SHelen Koike 1599e6938cc1SHelen Koike spin_lock_irq(¶ms->config_lock); 1600e6938cc1SHelen Koike 1601e6938cc1SHelen Koike /* apply the first buffer if there is one already */ 1602e6938cc1SHelen Koike rkisp1_params_apply_params_cfg(params, 0); 1603e6938cc1SHelen Koike 1604e6938cc1SHelen Koike spin_unlock_irq(¶ms->config_lock); 1605e6938cc1SHelen Koike } 1606e6938cc1SHelen Koike 1607e6938cc1SHelen Koike void rkisp1_params_configure(struct rkisp1_params *params, 1608e6938cc1SHelen Koike enum rkisp1_fmt_raw_pat_type bayer_pat, 1609f7aa2d23SLaurent Pinchart enum v4l2_quantization quantization, 1610f7aa2d23SLaurent Pinchart enum v4l2_ycbcr_encoding ycbcr_encoding) 1611e6938cc1SHelen Koike { 1612e6938cc1SHelen Koike params->quantization = quantization; 1613f7aa2d23SLaurent Pinchart params->ycbcr_encoding = ycbcr_encoding; 1614e6938cc1SHelen Koike params->raw_type = bayer_pat; 1615e6938cc1SHelen Koike rkisp1_params_config_parameter(params); 1616e6938cc1SHelen Koike } 1617e6938cc1SHelen Koike 161827ba4427SSebastian Fricke /* 161927ba4427SSebastian Fricke * Not called when the camera is active, therefore there is no need to acquire 162027ba4427SSebastian Fricke * a lock. 162127ba4427SSebastian Fricke */ 1622e6938cc1SHelen Koike void rkisp1_params_disable(struct rkisp1_params *params) 1623e6938cc1SHelen Koike { 1624e6938cc1SHelen Koike rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_DPCC_MODE, 16259daa2b84SLaurent Pinchart RKISP1_CIF_ISP_DPCC_MODE_DPCC_ENABLE); 1626e6938cc1SHelen Koike rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_LSC_CTRL, 1627e6938cc1SHelen Koike RKISP1_CIF_ISP_LSC_CTRL_ENA); 1628e6938cc1SHelen Koike rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_BLS_CTRL, 1629e6938cc1SHelen Koike RKISP1_CIF_ISP_BLS_ENA); 1630e6938cc1SHelen Koike rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_CTRL, 1631e6938cc1SHelen Koike RKISP1_CIF_ISP_CTRL_ISP_GAMMA_IN_ENA); 1632e6938cc1SHelen Koike rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_CTRL, 1633e6938cc1SHelen Koike RKISP1_CIF_ISP_CTRL_ISP_GAMMA_OUT_ENA); 1634e6938cc1SHelen Koike rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_DEMOSAIC, 1635e6938cc1SHelen Koike RKISP1_CIF_ISP_DEMOSAIC_BYPASS); 1636e6938cc1SHelen Koike rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_FILT_MODE, 1637e6938cc1SHelen Koike RKISP1_CIF_ISP_FLT_ENA); 16385e8d9d72SHeiko Stuebner params->ops->awb_meas_enable(params, NULL, false); 1639e6938cc1SHelen Koike rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_CTRL, 1640e6938cc1SHelen Koike RKISP1_CIF_ISP_CTRL_ISP_AWB_ENA); 1641e6938cc1SHelen Koike rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_EXP_CTRL, 1642e6938cc1SHelen Koike RKISP1_CIF_ISP_EXP_ENA); 1643e6938cc1SHelen Koike rkisp1_ctk_enable(params, false); 1644e6938cc1SHelen Koike rkisp1_param_clear_bits(params, RKISP1_CIF_C_PROC_CTRL, 1645e6938cc1SHelen Koike RKISP1_CIF_C_PROC_CTR_ENABLE); 16465e8d9d72SHeiko Stuebner params->ops->hst_enable(params, NULL, false); 1647e6938cc1SHelen Koike rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_AFM_CTRL, 1648e6938cc1SHelen Koike RKISP1_CIF_ISP_AFM_ENA); 1649e6938cc1SHelen Koike rkisp1_ie_enable(params, false); 1650e6938cc1SHelen Koike rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_DPF_MODE, 1651e6938cc1SHelen Koike RKISP1_CIF_ISP_DPF_MODE_EN); 1652e6938cc1SHelen Koike } 1653e6938cc1SHelen Koike 1654dce8ccb2SHeiko Stuebner static const struct rkisp1_params_ops rkisp1_v10_params_ops = { 1655dce8ccb2SHeiko Stuebner .lsc_matrix_config = rkisp1_lsc_matrix_config_v10, 1656dce8ccb2SHeiko Stuebner .goc_config = rkisp1_goc_config_v10, 1657dce8ccb2SHeiko Stuebner .awb_meas_config = rkisp1_awb_meas_config_v10, 1658dce8ccb2SHeiko Stuebner .awb_meas_enable = rkisp1_awb_meas_enable_v10, 1659dce8ccb2SHeiko Stuebner .awb_gain_config = rkisp1_awb_gain_config_v10, 1660dce8ccb2SHeiko Stuebner .aec_config = rkisp1_aec_config_v10, 1661dce8ccb2SHeiko Stuebner .hst_config = rkisp1_hst_config_v10, 1662dce8ccb2SHeiko Stuebner .hst_enable = rkisp1_hst_enable_v10, 1663dce8ccb2SHeiko Stuebner .afm_config = rkisp1_afm_config_v10, 16645e8d9d72SHeiko Stuebner }; 16655e8d9d72SHeiko Stuebner 1666cd42f802SHeiko Stuebner static struct rkisp1_params_ops rkisp1_v12_params_ops = { 1667cd42f802SHeiko Stuebner .lsc_matrix_config = rkisp1_lsc_matrix_config_v12, 1668cd42f802SHeiko Stuebner .goc_config = rkisp1_goc_config_v12, 1669cd42f802SHeiko Stuebner .awb_meas_config = rkisp1_awb_meas_config_v12, 1670cd42f802SHeiko Stuebner .awb_meas_enable = rkisp1_awb_meas_enable_v12, 1671cd42f802SHeiko Stuebner .awb_gain_config = rkisp1_awb_gain_config_v12, 1672cd42f802SHeiko Stuebner .aec_config = rkisp1_aec_config_v12, 1673cd42f802SHeiko Stuebner .hst_config = rkisp1_hst_config_v12, 1674cd42f802SHeiko Stuebner .hst_enable = rkisp1_hst_enable_v12, 1675cd42f802SHeiko Stuebner .afm_config = rkisp1_afm_config_v12, 1676cd42f802SHeiko Stuebner }; 1677cd42f802SHeiko Stuebner 1678e6938cc1SHelen Koike static int rkisp1_params_enum_fmt_meta_out(struct file *file, void *priv, 1679e6938cc1SHelen Koike struct v4l2_fmtdesc *f) 1680e6938cc1SHelen Koike { 1681e6938cc1SHelen Koike struct video_device *video = video_devdata(file); 1682e6938cc1SHelen Koike struct rkisp1_params *params = video_get_drvdata(video); 1683e6938cc1SHelen Koike 1684e6938cc1SHelen Koike if (f->index > 0 || f->type != video->queue->type) 1685e6938cc1SHelen Koike return -EINVAL; 1686e6938cc1SHelen Koike 1687e6938cc1SHelen Koike f->pixelformat = params->vdev_fmt.fmt.meta.dataformat; 1688e6938cc1SHelen Koike 1689e6938cc1SHelen Koike return 0; 1690e6938cc1SHelen Koike } 1691e6938cc1SHelen Koike 1692e6938cc1SHelen Koike static int rkisp1_params_g_fmt_meta_out(struct file *file, void *fh, 1693e6938cc1SHelen Koike struct v4l2_format *f) 1694e6938cc1SHelen Koike { 1695e6938cc1SHelen Koike struct video_device *video = video_devdata(file); 1696e6938cc1SHelen Koike struct rkisp1_params *params = video_get_drvdata(video); 1697e6938cc1SHelen Koike struct v4l2_meta_format *meta = &f->fmt.meta; 1698e6938cc1SHelen Koike 1699e6938cc1SHelen Koike if (f->type != video->queue->type) 1700e6938cc1SHelen Koike return -EINVAL; 1701e6938cc1SHelen Koike 1702e6938cc1SHelen Koike memset(meta, 0, sizeof(*meta)); 1703e6938cc1SHelen Koike meta->dataformat = params->vdev_fmt.fmt.meta.dataformat; 1704e6938cc1SHelen Koike meta->buffersize = params->vdev_fmt.fmt.meta.buffersize; 1705e6938cc1SHelen Koike 1706e6938cc1SHelen Koike return 0; 1707e6938cc1SHelen Koike } 1708e6938cc1SHelen Koike 1709e6938cc1SHelen Koike static int rkisp1_params_querycap(struct file *file, 1710e6938cc1SHelen Koike void *priv, struct v4l2_capability *cap) 1711e6938cc1SHelen Koike { 1712e6938cc1SHelen Koike struct video_device *vdev = video_devdata(file); 1713e6938cc1SHelen Koike 1714e6938cc1SHelen Koike strscpy(cap->driver, RKISP1_DRIVER_NAME, sizeof(cap->driver)); 1715e6938cc1SHelen Koike strscpy(cap->card, vdev->name, sizeof(cap->card)); 1716e6938cc1SHelen Koike strscpy(cap->bus_info, RKISP1_BUS_INFO, sizeof(cap->bus_info)); 1717e6938cc1SHelen Koike 1718e6938cc1SHelen Koike return 0; 1719e6938cc1SHelen Koike } 1720e6938cc1SHelen Koike 1721e6938cc1SHelen Koike /* ISP params video device IOCTLs */ 1722e6938cc1SHelen Koike static const struct v4l2_ioctl_ops rkisp1_params_ioctl = { 1723e6938cc1SHelen Koike .vidioc_reqbufs = vb2_ioctl_reqbufs, 1724e6938cc1SHelen Koike .vidioc_querybuf = vb2_ioctl_querybuf, 1725e6938cc1SHelen Koike .vidioc_create_bufs = vb2_ioctl_create_bufs, 1726e6938cc1SHelen Koike .vidioc_qbuf = vb2_ioctl_qbuf, 1727e6938cc1SHelen Koike .vidioc_dqbuf = vb2_ioctl_dqbuf, 1728e6938cc1SHelen Koike .vidioc_prepare_buf = vb2_ioctl_prepare_buf, 1729e6938cc1SHelen Koike .vidioc_expbuf = vb2_ioctl_expbuf, 1730e6938cc1SHelen Koike .vidioc_streamon = vb2_ioctl_streamon, 1731e6938cc1SHelen Koike .vidioc_streamoff = vb2_ioctl_streamoff, 1732e6938cc1SHelen Koike .vidioc_enum_fmt_meta_out = rkisp1_params_enum_fmt_meta_out, 1733e6938cc1SHelen Koike .vidioc_g_fmt_meta_out = rkisp1_params_g_fmt_meta_out, 1734e6938cc1SHelen Koike .vidioc_s_fmt_meta_out = rkisp1_params_g_fmt_meta_out, 1735e6938cc1SHelen Koike .vidioc_try_fmt_meta_out = rkisp1_params_g_fmt_meta_out, 1736e6938cc1SHelen Koike .vidioc_querycap = rkisp1_params_querycap, 1737e6938cc1SHelen Koike .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, 1738e6938cc1SHelen Koike .vidioc_unsubscribe_event = v4l2_event_unsubscribe, 1739e6938cc1SHelen Koike }; 1740e6938cc1SHelen Koike 1741e6938cc1SHelen Koike static int rkisp1_params_vb2_queue_setup(struct vb2_queue *vq, 1742e6938cc1SHelen Koike unsigned int *num_buffers, 1743e6938cc1SHelen Koike unsigned int *num_planes, 1744e6938cc1SHelen Koike unsigned int sizes[], 1745e6938cc1SHelen Koike struct device *alloc_devs[]) 1746e6938cc1SHelen Koike { 1747e6938cc1SHelen Koike *num_buffers = clamp_t(u32, *num_buffers, 1748e6938cc1SHelen Koike RKISP1_ISP_PARAMS_REQ_BUFS_MIN, 1749e6938cc1SHelen Koike RKISP1_ISP_PARAMS_REQ_BUFS_MAX); 1750e6938cc1SHelen Koike 1751e6938cc1SHelen Koike *num_planes = 1; 1752e6938cc1SHelen Koike 1753e6938cc1SHelen Koike sizes[0] = sizeof(struct rkisp1_params_cfg); 1754e6938cc1SHelen Koike 1755e6938cc1SHelen Koike return 0; 1756e6938cc1SHelen Koike } 1757e6938cc1SHelen Koike 1758e6938cc1SHelen Koike static void rkisp1_params_vb2_buf_queue(struct vb2_buffer *vb) 1759e6938cc1SHelen Koike { 1760e6938cc1SHelen Koike struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 1761e6938cc1SHelen Koike struct rkisp1_buffer *params_buf = 1762e6938cc1SHelen Koike container_of(vbuf, struct rkisp1_buffer, vb); 1763e6938cc1SHelen Koike struct vb2_queue *vq = vb->vb2_queue; 1764e6938cc1SHelen Koike struct rkisp1_params *params = vq->drv_priv; 1765e6938cc1SHelen Koike 1766e6938cc1SHelen Koike spin_lock_irq(¶ms->config_lock); 1767e6938cc1SHelen Koike list_add_tail(¶ms_buf->queue, ¶ms->params); 1768e6938cc1SHelen Koike spin_unlock_irq(¶ms->config_lock); 1769e6938cc1SHelen Koike } 1770e6938cc1SHelen Koike 1771e6938cc1SHelen Koike static int rkisp1_params_vb2_buf_prepare(struct vb2_buffer *vb) 1772e6938cc1SHelen Koike { 1773e6938cc1SHelen Koike if (vb2_plane_size(vb, 0) < sizeof(struct rkisp1_params_cfg)) 1774e6938cc1SHelen Koike return -EINVAL; 1775e6938cc1SHelen Koike 1776e6938cc1SHelen Koike vb2_set_plane_payload(vb, 0, sizeof(struct rkisp1_params_cfg)); 1777e6938cc1SHelen Koike 1778e6938cc1SHelen Koike return 0; 1779e6938cc1SHelen Koike } 1780e6938cc1SHelen Koike 1781e6938cc1SHelen Koike static void rkisp1_params_vb2_stop_streaming(struct vb2_queue *vq) 1782e6938cc1SHelen Koike { 1783e6938cc1SHelen Koike struct rkisp1_params *params = vq->drv_priv; 1784e6938cc1SHelen Koike struct rkisp1_buffer *buf; 1785e6938cc1SHelen Koike LIST_HEAD(tmp_list); 1786e6938cc1SHelen Koike 1787e6938cc1SHelen Koike /* 1788e6938cc1SHelen Koike * we first move the buffers into a local list 'tmp_list' 1789e6938cc1SHelen Koike * and then we can iterate it and call vb2_buffer_done 1790e6938cc1SHelen Koike * without holding the lock 1791e6938cc1SHelen Koike */ 1792e6938cc1SHelen Koike spin_lock_irq(¶ms->config_lock); 1793e6938cc1SHelen Koike list_splice_init(¶ms->params, &tmp_list); 1794e6938cc1SHelen Koike spin_unlock_irq(¶ms->config_lock); 1795e6938cc1SHelen Koike 1796e6938cc1SHelen Koike list_for_each_entry(buf, &tmp_list, queue) 1797e6938cc1SHelen Koike vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); 1798e6938cc1SHelen Koike } 1799e6938cc1SHelen Koike 1800a109073bSRikard Falkeborn static const struct vb2_ops rkisp1_params_vb2_ops = { 1801e6938cc1SHelen Koike .queue_setup = rkisp1_params_vb2_queue_setup, 1802e6938cc1SHelen Koike .wait_prepare = vb2_ops_wait_prepare, 1803e6938cc1SHelen Koike .wait_finish = vb2_ops_wait_finish, 1804e6938cc1SHelen Koike .buf_queue = rkisp1_params_vb2_buf_queue, 1805e6938cc1SHelen Koike .buf_prepare = rkisp1_params_vb2_buf_prepare, 1806e6938cc1SHelen Koike .stop_streaming = rkisp1_params_vb2_stop_streaming, 1807e6938cc1SHelen Koike 1808e6938cc1SHelen Koike }; 1809e6938cc1SHelen Koike 1810a109073bSRikard Falkeborn static const struct v4l2_file_operations rkisp1_params_fops = { 1811e6938cc1SHelen Koike .mmap = vb2_fop_mmap, 1812e6938cc1SHelen Koike .unlocked_ioctl = video_ioctl2, 1813e6938cc1SHelen Koike .poll = vb2_fop_poll, 1814e6938cc1SHelen Koike .open = v4l2_fh_open, 1815e6938cc1SHelen Koike .release = vb2_fop_release 1816e6938cc1SHelen Koike }; 1817e6938cc1SHelen Koike 1818e6938cc1SHelen Koike static int rkisp1_params_init_vb2_queue(struct vb2_queue *q, 1819e6938cc1SHelen Koike struct rkisp1_params *params) 1820e6938cc1SHelen Koike { 1821e6938cc1SHelen Koike struct rkisp1_vdev_node *node; 1822e6938cc1SHelen Koike 1823e6938cc1SHelen Koike node = container_of(q, struct rkisp1_vdev_node, buf_queue); 1824e6938cc1SHelen Koike 1825e6938cc1SHelen Koike q->type = V4L2_BUF_TYPE_META_OUTPUT; 1826e6938cc1SHelen Koike q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; 1827e6938cc1SHelen Koike q->drv_priv = params; 1828e6938cc1SHelen Koike q->ops = &rkisp1_params_vb2_ops; 1829e6938cc1SHelen Koike q->mem_ops = &vb2_vmalloc_memops; 1830e6938cc1SHelen Koike q->buf_struct_size = sizeof(struct rkisp1_buffer); 1831e6938cc1SHelen Koike q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; 1832e6938cc1SHelen Koike q->lock = &node->vlock; 1833e6938cc1SHelen Koike 1834e6938cc1SHelen Koike return vb2_queue_init(q); 1835e6938cc1SHelen Koike } 1836e6938cc1SHelen Koike 1837e6938cc1SHelen Koike static void rkisp1_init_params(struct rkisp1_params *params) 1838e6938cc1SHelen Koike { 1839e6938cc1SHelen Koike params->vdev_fmt.fmt.meta.dataformat = 1840e6938cc1SHelen Koike V4L2_META_FMT_RK_ISP1_PARAMS; 1841e6938cc1SHelen Koike params->vdev_fmt.fmt.meta.buffersize = 1842e6938cc1SHelen Koike sizeof(struct rkisp1_params_cfg); 18435e8d9d72SHeiko Stuebner 18441195b18cSLaurent Pinchart if (params->rkisp1->info->isp_ver == RKISP1_V12) 1845cd42f802SHeiko Stuebner params->ops = &rkisp1_v12_params_ops; 1846cd42f802SHeiko Stuebner else 1847dce8ccb2SHeiko Stuebner params->ops = &rkisp1_v10_params_ops; 1848e6938cc1SHelen Koike } 1849e6938cc1SHelen Koike 1850e6938cc1SHelen Koike int rkisp1_params_register(struct rkisp1_device *rkisp1) 1851e6938cc1SHelen Koike { 1852e6938cc1SHelen Koike struct rkisp1_params *params = &rkisp1->params; 1853e6938cc1SHelen Koike struct rkisp1_vdev_node *node = ¶ms->vnode; 1854e6938cc1SHelen Koike struct video_device *vdev = &node->vdev; 1855e6938cc1SHelen Koike int ret; 1856e6938cc1SHelen Koike 1857e6938cc1SHelen Koike params->rkisp1 = rkisp1; 1858e6938cc1SHelen Koike mutex_init(&node->vlock); 1859e6938cc1SHelen Koike INIT_LIST_HEAD(¶ms->params); 1860e6938cc1SHelen Koike spin_lock_init(¶ms->config_lock); 1861e6938cc1SHelen Koike 1862e6938cc1SHelen Koike strscpy(vdev->name, RKISP1_PARAMS_DEV_NAME, sizeof(vdev->name)); 1863e6938cc1SHelen Koike 1864e6938cc1SHelen Koike video_set_drvdata(vdev, params); 1865e6938cc1SHelen Koike vdev->ioctl_ops = &rkisp1_params_ioctl; 1866e6938cc1SHelen Koike vdev->fops = &rkisp1_params_fops; 1867e6938cc1SHelen Koike vdev->release = video_device_release_empty; 1868e6938cc1SHelen Koike /* 1869e6938cc1SHelen Koike * Provide a mutex to v4l2 core. It will be used 1870e6938cc1SHelen Koike * to protect all fops and v4l2 ioctls. 1871e6938cc1SHelen Koike */ 1872e6938cc1SHelen Koike vdev->lock = &node->vlock; 1873e6938cc1SHelen Koike vdev->v4l2_dev = &rkisp1->v4l2_dev; 1874e6938cc1SHelen Koike vdev->queue = &node->buf_queue; 1875e6938cc1SHelen Koike vdev->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_META_OUTPUT; 1876e6938cc1SHelen Koike vdev->vfl_dir = VFL_DIR_TX; 1877e6938cc1SHelen Koike rkisp1_params_init_vb2_queue(vdev->queue, params); 1878e6938cc1SHelen Koike rkisp1_init_params(params); 1879e6938cc1SHelen Koike video_set_drvdata(vdev, params); 1880e6938cc1SHelen Koike 1881e6938cc1SHelen Koike node->pad.flags = MEDIA_PAD_FL_SOURCE; 1882e6938cc1SHelen Koike ret = media_entity_pads_init(&vdev->entity, 1, &node->pad); 1883e6938cc1SHelen Koike if (ret) 18848ba4862eSLaurent Pinchart goto error; 18858ba4862eSLaurent Pinchart 1886e6938cc1SHelen Koike ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1); 1887e6938cc1SHelen Koike if (ret) { 1888e6938cc1SHelen Koike dev_err(rkisp1->dev, 1889e6938cc1SHelen Koike "failed to register %s, ret=%d\n", vdev->name, ret); 18908ba4862eSLaurent Pinchart goto error; 1891e6938cc1SHelen Koike } 18928ba4862eSLaurent Pinchart 1893e6938cc1SHelen Koike return 0; 18948ba4862eSLaurent Pinchart 18958ba4862eSLaurent Pinchart error: 1896e6938cc1SHelen Koike media_entity_cleanup(&vdev->entity); 18978ba4862eSLaurent Pinchart mutex_destroy(&node->vlock); 1898e6938cc1SHelen Koike return ret; 1899e6938cc1SHelen Koike } 1900e6938cc1SHelen Koike 1901e6938cc1SHelen Koike void rkisp1_params_unregister(struct rkisp1_device *rkisp1) 1902e6938cc1SHelen Koike { 1903e6938cc1SHelen Koike struct rkisp1_params *params = &rkisp1->params; 1904e6938cc1SHelen Koike struct rkisp1_vdev_node *node = ¶ms->vnode; 1905e6938cc1SHelen Koike struct video_device *vdev = &node->vdev; 1906e6938cc1SHelen Koike 19078ba4862eSLaurent Pinchart if (!video_is_registered(vdev)) 19088ba4862eSLaurent Pinchart return; 19098ba4862eSLaurent Pinchart 1910e6938cc1SHelen Koike vb2_video_unregister_device(vdev); 1911e6938cc1SHelen Koike media_entity_cleanup(&vdev->entity); 19128ba4862eSLaurent Pinchart mutex_destroy(&node->vlock); 1913e6938cc1SHelen Koike } 1914