@@ -5,6 +5,7 @@
* Copyright (C) 2017 Rockchip Electronics Co., Ltd.
*/
+#include <linux/math.h>
#include <linux/string.h>
#include <media/v4l2-common.h>
@@ -57,6 +58,8 @@ union rkisp1_ext_params_config {
struct rkisp1_ext_params_hst_config hst;
struct rkisp1_ext_params_aec_config aec;
struct rkisp1_ext_params_afc_config afc;
+ struct rkisp1_ext_params_compand_bls_config compand_bls;
+ struct rkisp1_ext_params_compand_curve_config compand_curve;
};
enum rkisp1_params_formats {
@@ -1258,6 +1261,93 @@ rkisp1_dpf_strength_config(struct rkisp1_params *params,
rkisp1_write(params->rkisp1, RKISP1_CIF_ISP_DPF_STRENGTH_R, arg->r);
}
+static void rkisp1_compand_write_px_curve(struct rkisp1_params *params,
+ unsigned int addr, const u8 *curve)
+{
+ const unsigned int points_per_reg = 6;
+ const unsigned int num_regs =
+ DIV_ROUND_UP(RKISP1_CIF_ISP_COMPAND_NUM_POINTS,
+ points_per_reg);
+
+ /*
+ * The compand curve is specified as a piecewise linear function with
+ * 64 points. X coordinates are stored as a log2 of the displacement
+ * from the previous point, in 5 bits, with 6 values per register. The
+ * last register stores 4 values.
+ */
+ for (unsigned int reg = 0; reg < num_regs; ++reg) {
+ unsigned int num_points =
+ min(RKISP1_CIF_ISP_COMPAND_NUM_POINTS -
+ reg * points_per_reg, points_per_reg);
+ u32 val = 0;
+
+ for (unsigned int i = 0; i < num_points; i++)
+ val |= (*curve++ & 0x1f) << (i * 5);
+
+ rkisp1_write(params->rkisp1, addr, val);
+ addr += 4;
+ }
+}
+
+static void
+rkisp1_compand_write_curve_mem(struct rkisp1_params *params,
+ unsigned int reg_addr, unsigned int reg_data,
+ const u32 curve[RKISP1_CIF_ISP_COMPAND_NUM_POINTS])
+{
+ for (unsigned int i = 0; i < RKISP1_CIF_ISP_COMPAND_NUM_POINTS; i++) {
+ rkisp1_write(params->rkisp1, reg_addr, i);
+ rkisp1_write(params->rkisp1, reg_data, curve[i]);
+ }
+}
+
+static void
+rkisp1_compand_bls_config(struct rkisp1_params *params,
+ const struct rkisp1_cif_isp_compand_bls_config *arg)
+{
+ static const u32 regs[] = {
+ RKISP1_CIF_ISP_COMPAND_BLS_A_FIXED,
+ RKISP1_CIF_ISP_COMPAND_BLS_B_FIXED,
+ RKISP1_CIF_ISP_COMPAND_BLS_C_FIXED,
+ RKISP1_CIF_ISP_COMPAND_BLS_D_FIXED,
+ };
+ u32 swapped[4];
+
+ rkisp1_bls_swap_regs(params->raw_type, regs, swapped);
+
+ rkisp1_write(params->rkisp1, swapped[0], arg->r);
+ rkisp1_write(params->rkisp1, swapped[1], arg->gr);
+ rkisp1_write(params->rkisp1, swapped[2], arg->gb);
+ rkisp1_write(params->rkisp1, swapped[3], arg->b);
+}
+
+static void
+rkisp1_compand_expand_config(struct rkisp1_params *params,
+ const struct rkisp1_cif_isp_compand_curve_config *arg)
+{
+ rkisp1_compand_write_px_curve(params, RKISP1_CIF_ISP_COMPAND_EXPAND_PX_N(0),
+ arg->px);
+ rkisp1_compand_write_curve_mem(params, RKISP1_CIF_ISP_COMPAND_EXPAND_Y_ADDR,
+ RKISP1_CIF_ISP_COMPAND_EXPAND_Y_WRITE_DATA,
+ arg->y);
+ rkisp1_compand_write_curve_mem(params, RKISP1_CIF_ISP_COMPAND_EXPAND_X_ADDR,
+ RKISP1_CIF_ISP_COMPAND_EXPAND_X_WRITE_DATA,
+ arg->x);
+}
+
+static void
+rkisp1_compand_compress_config(struct rkisp1_params *params,
+ const struct rkisp1_cif_isp_compand_curve_config *arg)
+{
+ rkisp1_compand_write_px_curve(params, RKISP1_CIF_ISP_COMPAND_COMPRESS_PX_N(0),
+ arg->px);
+ rkisp1_compand_write_curve_mem(params, RKISP1_CIF_ISP_COMPAND_COMPRESS_Y_ADDR,
+ RKISP1_CIF_ISP_COMPAND_COMPRESS_Y_WRITE_DATA,
+ arg->y);
+ rkisp1_compand_write_curve_mem(params, RKISP1_CIF_ISP_COMPAND_COMPRESS_X_ADDR,
+ RKISP1_CIF_ISP_COMPAND_COMPRESS_X_WRITE_DATA,
+ arg->x);
+}
+
static void
rkisp1_isp_isr_other_config(struct rkisp1_params *params,
const struct rkisp1_params_cfg *new_params)
@@ -1855,6 +1945,66 @@ rkisp1_ext_params_afcm(struct rkisp1_params *params,
RKISP1_CIF_ISP_AFM_ENA);
}
+static void rkisp1_ext_params_compand_bls(struct rkisp1_params *params,
+ const union rkisp1_ext_params_config *block)
+{
+ const struct rkisp1_ext_params_compand_bls_config *bls =
+ &block->compand_bls;
+
+ if (bls->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) {
+ rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_COMPAND_CTRL,
+ RKISP1_CIF_ISP_COMPAND_CTRL_BLS_ENABLE);
+ return;
+ }
+
+ rkisp1_compand_bls_config(params, &bls->config);
+
+ if ((bls->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_ENABLE) &&
+ !(params->enabled_blocks & BIT(bls->header.type)))
+ rkisp1_param_set_bits(params, RKISP1_CIF_ISP_COMPAND_CTRL,
+ RKISP1_CIF_ISP_COMPAND_CTRL_BLS_ENABLE);
+}
+
+static void rkisp1_ext_params_compand_expand(struct rkisp1_params *params,
+ const union rkisp1_ext_params_config *block)
+{
+ const struct rkisp1_ext_params_compand_curve_config *curve =
+ &block->compand_curve;
+
+ if (curve->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) {
+ rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_COMPAND_CTRL,
+ RKISP1_CIF_ISP_COMPAND_CTRL_EXPAND_ENABLE);
+ return;
+ }
+
+ rkisp1_compand_expand_config(params, &curve->config);
+
+ if ((curve->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_ENABLE) &&
+ !(params->enabled_blocks & BIT(curve->header.type)))
+ rkisp1_param_set_bits(params, RKISP1_CIF_ISP_COMPAND_CTRL,
+ RKISP1_CIF_ISP_COMPAND_CTRL_EXPAND_ENABLE);
+}
+
+static void rkisp1_ext_params_compand_compress(struct rkisp1_params *params,
+ const union rkisp1_ext_params_config *block)
+{
+ const struct rkisp1_ext_params_compand_curve_config *curve =
+ &block->compand_curve;
+
+ if (curve->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE) {
+ rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_COMPAND_CTRL,
+ RKISP1_CIF_ISP_COMPAND_CTRL_COMPRESS_ENABLE);
+ return;
+ }
+
+ rkisp1_compand_compress_config(params, &curve->config);
+
+ if ((curve->header.flags & RKISP1_EXT_PARAMS_FL_BLOCK_ENABLE) &&
+ !(params->enabled_blocks & BIT(curve->header.type)))
+ rkisp1_param_set_bits(params, RKISP1_CIF_ISP_COMPAND_CTRL,
+ RKISP1_CIF_ISP_COMPAND_CTRL_COMPRESS_ENABLE);
+}
+
typedef void (*rkisp1_block_handler)(struct rkisp1_params *params,
const union rkisp1_ext_params_config *config);
@@ -1950,6 +2100,24 @@ static const struct rkisp1_ext_params_handler {
.handler = rkisp1_ext_params_afcm,
.group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
},
+ [RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_BLS] = {
+ .size = sizeof(struct rkisp1_ext_params_compand_bls_config),
+ .handler = rkisp1_ext_params_compand_bls,
+ .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
+ .features = RKISP1_FEATURE_COMPAND,
+ },
+ [RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_EXPAND] = {
+ .size = sizeof(struct rkisp1_ext_params_compand_curve_config),
+ .handler = rkisp1_ext_params_compand_expand,
+ .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
+ .features = RKISP1_FEATURE_COMPAND,
+ },
+ [RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_COMPRESS] = {
+ .size = sizeof(struct rkisp1_ext_params_compand_curve_config),
+ .handler = rkisp1_ext_params_compand_compress,
+ .group = RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS,
+ .features = RKISP1_FEATURE_COMPAND,
+ },
};
static void rkisp1_ext_params_config(struct rkisp1_params *params,
@@ -164,6 +164,11 @@
#define RKISP1_CIF_ISP_DPF_MAX_NLF_COEFFS 17
#define RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS 6
+/*
+ * Compand
+ */
+#define RKISP1_CIF_ISP_COMPAND_NUM_POINTS 64
+
/*
* Measurement types
*/
@@ -851,6 +856,39 @@ struct rkisp1_params_cfg {
struct rkisp1_cif_isp_isp_other_cfg others;
};
+/**
+ * struct rkisp1_cif_isp_compand_bls_config - Rockchip ISP1 Companding parameters (BLS)
+ * @r: Fixed subtraction value for Bayer pattern R
+ * @gr: Fixed subtraction value for Bayer pattern Gr
+ * @gb: Fixed subtraction value for Bayer pattern Gb
+ * @b: Fixed subtraction value for Bayer pattern B
+ *
+ * The values will be subtracted from the sensor values. Note that unlike the
+ * dedicated BLS block, the BLS values in the compander are 20-bit unsigned.
+ */
+struct rkisp1_cif_isp_compand_bls_config {
+ __u32 r;
+ __u32 gr;
+ __u32 gb;
+ __u32 b;
+};
+
+/**
+ * struct rkisp1_cif_isp_compand_curve_config - Rockchip ISP1 Companding
+ * parameters (expand and compression curves)
+ * @px: Compand curve x-values. Each value stores the distance from the
+ * previous x-value, expressed as log2 of the distance on 5 bits.
+ * @x: Compand curve x-values. The functionality of these parameters are
+ * unknown due to do a lack of hardware documentation, but these are left
+ * here for future compatibility purposes.
+ * @y: Compand curve y-values
+ */
+struct rkisp1_cif_isp_compand_curve_config {
+ __u8 px[RKISP1_CIF_ISP_COMPAND_NUM_POINTS];
+ __u32 x[RKISP1_CIF_ISP_COMPAND_NUM_POINTS];
+ __u32 y[RKISP1_CIF_ISP_COMPAND_NUM_POINTS];
+};
+
/*---------- PART2: Measurement Statistics ------------*/
/**
@@ -1018,6 +1056,9 @@ struct rkisp1_stat_buffer {
* @RKISP1_EXT_PARAMS_BLOCK_TYPE_HST_MEAS: Histogram statistics
* @RKISP1_EXT_PARAMS_BLOCK_TYPE_AEC_MEAS: Auto exposure statistics
* @RKISP1_EXT_PARAMS_BLOCK_TYPE_AFC_MEAS: Auto-focus statistics
+ * @RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_BLS: BLS in the compand block
+ * @RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_EXPAND: Companding expand curve
+ * @RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_COMPRESS: Companding compress curve
*/
enum rkisp1_ext_params_block_type {
RKISP1_EXT_PARAMS_BLOCK_TYPE_BLS,
@@ -1037,6 +1078,9 @@ enum rkisp1_ext_params_block_type {
RKISP1_EXT_PARAMS_BLOCK_TYPE_HST_MEAS,
RKISP1_EXT_PARAMS_BLOCK_TYPE_AEC_MEAS,
RKISP1_EXT_PARAMS_BLOCK_TYPE_AFC_MEAS,
+ RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_BLS,
+ RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_EXPAND,
+ RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_COMPRESS,
};
#define RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE (1U << 0)
@@ -1380,6 +1424,46 @@ struct rkisp1_ext_params_afc_config {
struct rkisp1_cif_isp_afc_config config;
} __attribute__((aligned(8)));
+/**
+ * struct rkisp1_ext_params_compand_bls_config - RkISP1 extensible params
+ * Compand BLS config
+ *
+ * RkISP1 extensible parameters Companding configuration block (black level
+ * subtraction). Identified by :c:type:`RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_BLS`.
+ *
+ * @header: The RkISP1 extensible parameters header, see
+ * :c:type:`rkisp1_ext_params_block_header`
+ * @config: Companding BLS configuration, see
+ * :c:type:`rkisp1_cif_isp_compand_bls_config`
+ */
+struct rkisp1_ext_params_compand_bls_config {
+ struct rkisp1_ext_params_block_header header;
+ struct rkisp1_cif_isp_compand_bls_config config;
+} __attribute__((aligned(8)));
+
+/**
+ * struct rkisp1_ext_params_compand_curve_config - RkISP1 extensible params
+ * Compand curve config
+ *
+ * RkISP1 extensible parameters Companding configuration block (expand and
+ * compression curves). Identified by
+ * :c:type:`RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_EXPAND` or
+ * :c:type:`RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_COMPRESS`.
+ *
+ * @header: The RkISP1 extensible parameters header, see
+ * :c:type:`rkisp1_ext_params_block_header`
+ * @config: Companding curve configuration, see
+ * :c:type:`rkisp1_cif_isp_compand_curve_config`
+ */
+struct rkisp1_ext_params_compand_curve_config {
+ struct rkisp1_ext_params_block_header header;
+ struct rkisp1_cif_isp_compand_curve_config config;
+} __attribute__((aligned(8)));
+
+/*
+ * The rkisp1_ext_params_compand_curve_config structure is counted twice as it
+ * is used for both the COMPAND_EXPAND and COMPAND_COMPRESS block types.
+ */
#define RKISP1_EXT_PARAMS_MAX_SIZE \
(sizeof(struct rkisp1_ext_params_bls_config) +\
sizeof(struct rkisp1_ext_params_dpcc_config) +\
@@ -1397,7 +1481,10 @@ struct rkisp1_ext_params_afc_config {
sizeof(struct rkisp1_ext_params_awb_meas_config) +\
sizeof(struct rkisp1_ext_params_hst_config) +\
sizeof(struct rkisp1_ext_params_aec_config) +\
- sizeof(struct rkisp1_ext_params_afc_config))
+ sizeof(struct rkisp1_ext_params_afc_config) +\
+ sizeof(struct rkisp1_ext_params_compand_bls_config) +\
+ sizeof(struct rkisp1_ext_params_compand_curve_config) +\
+ sizeof(struct rkisp1_ext_params_compand_curve_config))
/**
* enum rksip1_ext_param_buffer_version - RkISP1 extensible parameters version