#define NUM_DEGAMMA_REGIONS 12
+/* Linear interpolation of tf_pts entries, where (i >> 4) is the integer tf_pts
+ * index, (i & 0xf) is the 1/16 sub-position.
+ */
+static struct fixed31_32 interp_tf_pts(const struct fixed31_32 *output_tf_channel, int i)
+{
+ struct fixed31_32 in_plus_one, in, value;
+ uint32_t t = i & 0xf;
+
+ in_plus_one = output_tf_channel[(i >> 4) + 1];
+ in = output_tf_channel[i >> 4];
+ value = dc_fixpt_sub(in_plus_one, in);
+ value = dc_fixpt_shr(dc_fixpt_mul_int(value, t), 4);
+ value = dc_fixpt_add(in, value);
+
+ return value;
+}
bool cm3_helper_translate_curve_to_degamma_hw_format(
const struct dc_transfer_func *output_tf,
j = 0;
for (k = 0; k < (region_end - region_start); k++) {
- increment = NUMBER_SW_SEGMENTS / (1 << seg_distr[k]);
+ increment = (NUMBER_SW_SEGMENTS << 4) / (1 << seg_distr[k]);
start_index = (region_start + k + MAX_LOW_POINT) *
NUMBER_SW_SEGMENTS;
- for (i = start_index; i < start_index + NUMBER_SW_SEGMENTS;
- i += increment) {
+ for (i = (start_index << 4);
+ i < (start_index << 4) + (NUMBER_SW_SEGMENTS << 4);
+ i += increment) {
if (j == hw_points - 1)
break;
- if (i >= TRANSFER_FUNC_POINTS)
+ if ((i >> 4) + 1 >= TRANSFER_FUNC_POINTS)
return false;
- rgb_resulted[j].red = output_tf->tf_pts.red[i];
- rgb_resulted[j].green = output_tf->tf_pts.green[i];
- rgb_resulted[j].blue = output_tf->tf_pts.blue[i];
+
+ rgb_resulted[j].red = interp_tf_pts(output_tf->tf_pts.red, i);
+ rgb_resulted[j].green = interp_tf_pts(output_tf->tf_pts.green, i);
+ rgb_resulted[j].blue = interp_tf_pts(output_tf->tf_pts.blue, i);
j++;
}
}