// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
/*
 * Copyright (c) 2020 MediaTek Inc.
 */

#include <linux/module.h>
#include <linux/delay.h>
#include <drm/mtk_tv_drm.h>

#include "mtk_tv_drm_log.h"
#include "mtk_tv_drm_common.h"
#include "mtk_tv_drm_pqgamma.h"
#include "mtk_tv_drm_window_report.h"

#include "hwreg_render_pqgamma.h"
#include "ext_command_render_if.h"

//--------------------------------------------------------------------------------------------------
//  Local Defines
//--------------------------------------------------------------------------------------------------
#define MTK_DRM_MODEL MTK_DRM_MODEL_PNLGAMMA
#define ERR(fmt, args...) DRM_ERROR("[%s][%d] " fmt, __func__, __LINE__, ##args)
#define LOG(fmt, args...) DRM_INFO("[%s][%d] " fmt, __func__, __LINE__, ##args)


#define COLOR_10b_TO_8b(c)	((c) >> 2)

#define DELAY_MS(freq1000)	(1500000 / (freq1000))  // delay 1.5 vsync

/* OLED window report */
#define OLED_SHM_OFFSET		0x603000
#define RGB_API_BASE		4
#define RGB_API_VALID		5
#define BUFFER_INDEX_ADDR	6
#define RGB_REPORT_BASE		0x100
#define Y_0			0
#define Y_540			540
#define Y_1080			1080
#define Y_1620			1620
#define BIT4			0x10
#define AMBILIGHT_WD_TIMEOUT	60
#define AMB_H_UNIT_SIZE		480
#define AMB_V_UNIT_SIZE		540
#define AMB_WIN_NUM		16
#define AMB_WIN_NUM_HALF	8
#define AMB_DRAM_SIZE		576


//--------------------------------------------------------------------------------------------------
//  Local Enum and Structures
//--------------------------------------------------------------------------------------------------
struct window_report_info {
	int init;
	uint8_t hw_ver;

	void *u64AmbilightVaddr;
	struct mtk_panel_context *pnl;
	int (*read_report)(struct window_report_info *info, struct drm_mtk_tv_window_report *data);

	// ignore init
	struct drm_mtk_tv_window_report last_report;
	int last_return;
	uint16_t option;
};

struct oled_window_report_data {
	struct drm_mtk_tv_pixels_report pixel[AMB_WIN_NUM];
};

enum oled_window_report_buffer {
	EN_BUFFER_0 = 0,
	EN_BUFFER_1,
	EN_BUFFER_2,
	EN_BUFFER_3,
	EN_BUFFER_MAX,
};

//--------------------------------------------------------------------------------------------------
//  Local Variables
//--------------------------------------------------------------------------------------------------
static struct window_report_info _info;

//--------------------------------------------------------------------------------------------------
//  Local Functions
//--------------------------------------------------------------------------------------------------
static int _mtk_tv_drm_oled_window_report_init(
	struct window_report_info *info,
	struct mtk_ld_context *ldm)
{
	void *va = NULL;

	if (ldm->u64LDM_phyAddress == 0 || ldm->u32LDM_mmapsize <= OLED_SHM_OFFSET) {
		ERR("invalid phy address or mmap size, phys:0x%llx, size:0x%x",
			ldm->u64LDM_phyAddress, ldm->u32LDM_mmapsize);
		return -EINVAL;
	}

	va = memremap((size_t)(ldm->u64LDM_phyAddress + ldm->u32Cpu_emi0_base + OLED_SHM_OFFSET),
				ldm->u32LDM_mmapsize - OLED_SHM_OFFSET,
				MEMREMAP_WB);
	if (va == NULL) {
		ERR("memremap error");
		return -ENOMEM;
	}
	memset(va + RGB_REPORT_BASE, 0, AMB_DRAM_SIZE);

	LOG("phys:0x%llx, emi:0x%x, virt:0x%lx",
		ldm->u64LDM_phyAddress, ldm->u32Cpu_emi0_base, (long)va);

	info->u64AmbilightVaddr = va;
	return 0;
}

static int _mtk_tv_drm_oled_window_report_is_data_enable(void)
{
	/* Addr: LD base addr + 0x603000 + 0x04, BIT: bit4 */
	return ((*(__u8 *)(_info.u64AmbilightVaddr + RGB_API_BASE)) & (BIT4));
}

static void _mtk_tv_drm_oled_window_report_set_buffer_index(enum oled_window_report_buffer eBuffer)
{
	/* Addr: LD base addr + 0x603000 + 0x06 */
	memset(_info.u64AmbilightVaddr + BUFFER_INDEX_ADDR, eBuffer, 1);
}

static int _mtk_tv_drm_oled_window_report_is_data_write_done(void)
{
	/* Addr: LD base addr + 0x603000 + 0x05 */
	return ((*(__u8 *)(_info.u64AmbilightVaddr + RGB_API_VALID)) == 1);
}

static void _mtk_tv_drm_oled_window_report_set_read_done(void)
{
	/* Addr: LD base addr + 0x603000 + 0x05 */
	memset(_info.u64AmbilightVaddr + RGB_API_VALID, 0, 1);
}

static enum oled_window_report_buffer _mtk_tv_drm_oled_window_report_check_buffer(
	struct drm_mtk_tv_vidwin_rect *vidwin_rect)
{
	enum oled_window_report_buffer eBuffer = EN_BUFFER_MAX;

	switch (vidwin_rect->u16Y) {
	case Y_0:
		if (vidwin_rect->u16Height <= Y_540)
			eBuffer = EN_BUFFER_2;
		else if (vidwin_rect->u16Height <= Y_1080)
			eBuffer = EN_BUFFER_0;
		else
			ERR("window not supported");
		break;
	case Y_540:
		if (vidwin_rect->u16Height <= Y_1080)
			eBuffer = EN_BUFFER_3;
		else
			ERR("window not supported");
		break;
	case Y_1080:
		if (vidwin_rect->u16Height <= Y_1080)
			eBuffer = EN_BUFFER_1;
		else
			ERR("window not supported");
		break;
	case Y_1620:
		eBuffer = EN_BUFFER_2;
		break;
	default:
		break;
	}

	LOG("x = %d, y = %d, w = %d, h = %d, Buffer index = %d",
		vidwin_rect->u16X, vidwin_rect->u16Y,
		vidwin_rect->u16Width, vidwin_rect->u16Height, eBuffer);

	return eBuffer;
}

static struct drm_mtk_tv_pixels_report _mtk_tv_drm_oled_window_report_sum(
	struct drm_mtk_tv_pixels_report pixels_report_1,
	struct drm_mtk_tv_pixels_report pixels_report_2)
{
	struct drm_mtk_tv_pixels_report pixels_report_sum = {0};

	if (pixels_report_2.u32RcrMin < pixels_report_1.u32RcrMin)
		pixels_report_sum.u32RcrMin = pixels_report_2.u32RcrMin;
	else
		pixels_report_sum.u32RcrMin = pixels_report_1.u32RcrMin;

	if (pixels_report_2.u32RcrMax > pixels_report_1.u32RcrMax)
		pixels_report_sum.u32RcrMax = pixels_report_2.u32RcrMax;
	else
		pixels_report_sum.u32RcrMax = pixels_report_1.u32RcrMax;

	if (pixels_report_2.u32GYMin < pixels_report_1.u32GYMin)
		pixels_report_sum.u32GYMin = pixels_report_2.u32GYMin;
	else
		pixels_report_sum.u32GYMin = pixels_report_1.u32GYMin;

	if (pixels_report_2.u32GYMax > pixels_report_1.u32GYMax)
		pixels_report_sum.u32GYMax = pixels_report_2.u32GYMax;
	else
		pixels_report_sum.u32GYMax = pixels_report_1.u32GYMax;

	if (pixels_report_2.u32BcbMin < pixels_report_1.u32BcbMin)
		pixels_report_sum.u32BcbMin = pixels_report_2.u32BcbMin;
	else
		pixels_report_sum.u32BcbMin = pixels_report_1.u32BcbMin;

	if (pixels_report_2.u32BcbMax > pixels_report_1.u32BcbMax)
		pixels_report_sum.u32BcbMax = pixels_report_2.u32BcbMax;
	else
		pixels_report_sum.u32BcbMax = pixels_report_1.u32BcbMax;

	pixels_report_sum.u32RCrAvg = pixels_report_1.u32RCrAvg + pixels_report_2.u32RCrAvg;
	pixels_report_sum.u32GYAvg = pixels_report_1.u32GYAvg + pixels_report_2.u32GYAvg;
	pixels_report_sum.u32BcbAvg = pixels_report_1.u32BcbAvg + pixels_report_2.u32BcbAvg;

	return pixels_report_sum;
}

static int _mtk_tv_drm_oled_window_report_read(
	struct window_report_info *info,
	struct drm_mtk_tv_window_report *data)
{
	enum oled_window_report_buffer eCurBufferIndex = EN_BUFFER_MAX;
	uint8_t u8ThreadWaitTime = 0;
	uint8_t u8TotalWindNum = 0;
	uint8_t u8StartWinNum = 0;
	struct drm_mtk_tv_pixels_report pixels_report_sum = {0};
	struct drm_mtk_tv_pixels_report pixels_report_avg = {0};
	struct oled_window_report_data *pixels_data = NULL;
	int x = 0;
	int ret = 0;

	if (_mtk_tv_drm_oled_window_report_is_data_enable() == false) {
		ERR("ALG is not enable");
		return -ENODEV;
	}

	/* Get Data Report Buffer Index*/
	eCurBufferIndex = _mtk_tv_drm_oled_window_report_check_buffer(&data->vidwin_rect);

	/* Set Data Report Buffer Index*/
	_mtk_tv_drm_oled_window_report_set_buffer_index(eCurBufferIndex);

	/* Set SW Read DONE for DARM update */
	_mtk_tv_drm_oled_window_report_set_read_done();

	/* Wait DRAM write done */
	while (_mtk_tv_drm_oled_window_report_is_data_write_done() == 0) {
		mdelay(1);
		u8ThreadWaitTime++;
		if (u8ThreadWaitTime == AMBILIGHT_WD_TIMEOUT) {
			ERR("DRAM write done timeout");
			return -EBUSY;
		}
	}

	u8TotalWindNum = (data->vidwin_rect.u16Width / AMB_H_UNIT_SIZE) *
				(data->vidwin_rect.u16Height / AMB_V_UNIT_SIZE);

	pixels_data = (struct oled_window_report_data *)(info->u64AmbilightVaddr + RGB_REPORT_BASE);
	if (pixels_data == NULL) {
		ERR("pixels_data is NULL");
		return -EINVAL;
	}

	/* Find Start window num in 4x8 windows*/
	switch (eCurBufferIndex) {
	case EN_BUFFER_0:
		if (data->vidwin_rect.u16Y == 0)
			u8StartWinNum = data->vidwin_rect.u16X / AMB_H_UNIT_SIZE;
		else
			u8StartWinNum = data->vidwin_rect.u16X / AMB_H_UNIT_SIZE + AMB_WIN_NUM_HALF;
		break;
	case EN_BUFFER_1:
		if (data->vidwin_rect.u16Y == Y_1080)
			u8StartWinNum = data->vidwin_rect.u16X / AMB_H_UNIT_SIZE;
		else
			u8StartWinNum = data->vidwin_rect.u16X / AMB_H_UNIT_SIZE + AMB_WIN_NUM_HALF;
		break;
	case EN_BUFFER_2:
		if (data->vidwin_rect.u16Y == 0)
			u8StartWinNum = data->vidwin_rect.u16X / AMB_H_UNIT_SIZE;
		else
			u8StartWinNum = data->vidwin_rect.u16X / AMB_H_UNIT_SIZE + AMB_WIN_NUM_HALF;
		break;
	case EN_BUFFER_3:
		if (data->vidwin_rect.u16Y == Y_540)
			u8StartWinNum = data->vidwin_rect.u16X / AMB_H_UNIT_SIZE;
		else
			u8StartWinNum = data->vidwin_rect.u16X / AMB_H_UNIT_SIZE + AMB_WIN_NUM_HALF;
		break;
	default:
		ERR("Find start buffer failed");
		ret = -ERANGE;
		u8StartWinNum = 0;
		break;
	}

	pixels_report_sum = pixels_data->pixel[u8StartWinNum];
	LOG("u8StartWinNum = %d", u8StartWinNum);

	if (data->vidwin_rect.u16Width / AMB_H_UNIT_SIZE > 1) {
		for (x = 1; x <= (data->vidwin_rect.u16Width / AMB_H_UNIT_SIZE - 1); x++) {
			pixels_report_sum = _mtk_tv_drm_oled_window_report_sum(
					pixels_report_sum,
					pixels_data->pixel[u8StartWinNum + x]);
		}
	}
	if (data->vidwin_rect.u16Height / AMB_V_UNIT_SIZE > 1) {
		for (x = 0; x <= (data->vidwin_rect.u16Width / AMB_H_UNIT_SIZE - 1); x++) {
			pixels_report_sum = _mtk_tv_drm_oled_window_report_sum(
					pixels_report_sum,
					pixels_data->pixel[u8StartWinNum + AMB_WIN_NUM_HALF + x]);
		}
	}

	pixels_report_avg.u32RcrMin = pixels_report_sum.u32RcrMin;
	pixels_report_avg.u32RcrMax = pixels_report_sum.u32RcrMax;
	pixels_report_avg.u32GYMin = pixels_report_sum.u32GYMin;
	pixels_report_avg.u32GYMax = pixels_report_sum.u32GYMax;
	pixels_report_avg.u32BcbMin = pixels_report_sum.u32BcbMin;
	pixels_report_avg.u32BcbMax = pixels_report_sum.u32BcbMax;
	pixels_report_avg.u32RCrAvg = pixels_report_sum.u32RCrAvg / u8TotalWindNum;
	pixels_report_avg.u32GYAvg = pixels_report_sum.u32GYAvg / u8TotalWindNum;
	pixels_report_avg.u32BcbAvg = pixels_report_sum.u32BcbAvg / u8TotalWindNum;

	data->pixels_report = pixels_report_avg;
	return ret;
}

static int _mtk_tv_drm_pqgamma_window_report_init(
	struct window_report_info *info,
	struct mtk_panel_context *pnl)
{
	info->pnl = pnl;
	return 0;
}

static int _mtk_tv_drm_pqgamma_window_report_read(
	struct window_report_info *info,
	struct drm_mtk_tv_window_report *data)
{
	struct hwreg_render_pqgamma_window_info window_info = {0};
	struct hwreg_render_pqgamma_color_report window_report = {0};
	uint32_t pnl_freq = info->pnl->outputTiming_info.u32OutputVfreq;
	uint32_t pnl_width = info->pnl->info.de_width;
	uint32_t pnl_height = info->pnl->info.de_height;
	uint32_t total_pixel = 0;
	int ret = 0;

	if (data->vidwin_rect.u16Width == 0 || data->vidwin_rect.u16Height == 0) {
		ERR("Invalid input, W=%d, H=%d",
			data->vidwin_rect.u16Width, data->vidwin_rect.u16Height);
		return -EINVAL;
	}
	if (data->vidwin_rect.u16X + data->vidwin_rect.u16Width > pnl_width) {
		ERR("window width is too long, %d + %d > %d",
			data->vidwin_rect.u16X, data->vidwin_rect.u16Width, pnl_width);
		return -EINVAL;
	}
	if (data->vidwin_rect.u16Y + data->vidwin_rect.u16Height > pnl_height) {
		ERR("window height is too long, %d + %d > %d",
			data->vidwin_rect.u16Y, data->vidwin_rect.u16Height, pnl_height);
		return -EINVAL;
	}

	switch (data->vidwin_rect.eType) {
	case E_MTK_DRM_WINRP_TYPE_PQGA_IN:
		window_info.type = WINRP_TPYE_PQGA_IN;
		break;
	case E_MTK_DRM_WINRP_TYPE_OSD_IN:
		window_info.type = WINRP_TPYE_OSD_IN;
		break;
	case E_MTK_DRM_WINRP_TYPE_LD_IN:
		window_info.type = WINRP_TPYE_LD_IN;
		break;
	case E_MTK_DRM_WINRP_TYPE_LD_OUT:
		window_info.type = WINRP_TPYE_LD_OUT;
		break;
	default:
		ERR("Invalid type %d", data->vidwin_rect.eType);
		return -EINVAL;
	}
	window_info.draw_en = data->vidwin_rect.bDrawEnable;
	window_info.draw_r  = data->vidwin_rect.u32DrawRcr;
	window_info.draw_g  = data->vidwin_rect.u32DrawGY;
	window_info.draw_b  = data->vidwin_rect.u32DrawBcb;
	window_info.x_start = data->vidwin_rect.u16X;
	window_info.x_end   = data->vidwin_rect.u16X + data->vidwin_rect.u16Width - 1;
	window_info.y_start = data->vidwin_rect.u16Y;
	window_info.y_end   = data->vidwin_rect.u16Y + data->vidwin_rect.u16Height - 1;
	LOG("X:[%4d, %4d], Y:[%4d, %4d], pnl:[freq:%d, width:%d, height:%d]",
		window_info.x_start, window_info.x_end, window_info.y_start, window_info.y_end,
		pnl_freq, pnl_width, pnl_height);

	ret = drv_hwreg_render_pqgamma_set_window_report(&window_info);
	if (ret) {
		ERR("set hwreg fail, ret=%d", ret);
		return ret;
	}

	msleep(DELAY_MS(pnl_freq));

	ret = drv_hwreg_render_pqgamma_get_window_report(&window_report);
	if (ret) {
		ERR("get fail, ret=%d", ret);
		return ret;
	}
	total_pixel = data->vidwin_rect.u16Width * data->vidwin_rect.u16Height;

	data->pixels_report.u32RcrMin = COLOR_10b_TO_8b(window_report.min.R);
	data->pixels_report.u32GYMin  = COLOR_10b_TO_8b(window_report.min.G);
	data->pixels_report.u32BcbMin = COLOR_10b_TO_8b(window_report.min.B);
	data->pixels_report.u32RcrMax = COLOR_10b_TO_8b(window_report.max.R);
	data->pixels_report.u32GYMax  = COLOR_10b_TO_8b(window_report.max.G);
	data->pixels_report.u32BcbMax = COLOR_10b_TO_8b(window_report.max.B);
	data->pixels_report.u32RCrAvg = COLOR_10b_TO_8b(window_report.sum.R / total_pixel);
	data->pixels_report.u32GYAvg  = COLOR_10b_TO_8b(window_report.sum.G / total_pixel);
	data->pixels_report.u32BcbAvg = COLOR_10b_TO_8b(window_report.sum.B / total_pixel);
	return 0;
}

static int _mtk_tv_drm_window_report_init(
	struct window_report_info *info,
	struct mtk_tv_kms_context *kms)
{
	int ret = 0;

	switch (kms->globalpq_hw_ver.pqgamma_version) {
	case PQGAMMA_HW_VER_0:
	case PQGAMMA_HW_VER_1:
		LOG("Window Report from SW");
		ret = _mtk_tv_drm_oled_window_report_init(info, &kms->ld_priv);
		if (ret) {
			ERR("oled window report init fail, ret = %d", ret);
			return ret;
		}
		info->read_report = _mtk_tv_drm_oled_window_report_read;
		break;

	case PQGAMMA_HW_VER_2:
	case PQGAMMA_HW_VER_3:
		LOG("Window Report from HW");
		ret = _mtk_tv_drm_pqgamma_window_report_init(info, &kms->panel_priv);
		if (ret) {
			ERR("pqgamma window report init fail, ret = %d", ret);
			return ret;
		}
		info->read_report = _mtk_tv_drm_pqgamma_window_report_read;
		break;

	default:
		ERR("undefined PQGA version:%d", kms->globalpq_hw_ver.pqgamma_version);
		return -EINVAL;
	}
	info->hw_ver = kms->globalpq_hw_ver.pqgamma_version;
	info->init = true;
	return 0;
}

//--------------------------------------------------------------------------------------------------
//  Global Functions
//--------------------------------------------------------------------------------------------------
int mtk_tv_drm_window_report_read(
	struct mtk_tv_kms_context *kms,
	struct drm_mtk_tv_window_report *data)
{
	struct window_report_info *info = &_info;
	int ret = 0;

	if (!kms || !data) {
		ERR("null ptr, kms=%p, data=%p\n", kms, data);
		return -EINVAL;
	}
	if (info->init != true) {
		ret = _mtk_tv_drm_window_report_init(info, kms);
		if (ret) {
			ERR("Init fail, ver=%d, ret=%d", kms->globalpq_hw_ver.pqgamma_version, ret);
			return ret;
		}
	}
	ret = info->read_report(info, data);
	if (ret)
		ERR("read fail, ver=%d, ret=%d", kms->globalpq_hw_ver.pqgamma_version, ret);

	info->last_report = *data;
	info->last_return = ret;
	return ret;
}

int mtk_tv_drm_window_report_ioctl(
	struct drm_device *dev, void *data, struct drm_file *file_priv)
{
	struct mtk_tv_drm_crtc *mtk_tv_crtc = NULL;
	struct drm_crtc *crtc = NULL;

	if (!dev || !data || !file_priv) {
		ERR("Invalid input");
		return -EINVAL;
	}

	drm_for_each_crtc(crtc, dev) {
		mtk_tv_crtc = to_mtk_tv_crtc(crtc);
		break;
	}
	return mtk_tv_drm_window_report_read(
		(struct mtk_tv_kms_context *)mtk_tv_crtc->crtc_private,
		(struct drm_mtk_tv_window_report *)data);
}

ssize_t window_report_show(struct device *dev,
	struct device_attribute *attr, char *buf)
{
	struct window_report_info *info = &_info;
	struct mtk_tv_kms_context *kms = dev_get_drvdata(dev);
	int len = 0;

	SYSFS_PRINT(len, buf, "PQ Gamma version = %d", kms->globalpq_hw_ver.pqgamma_version);
	SYSFS_PRINT(len, buf, "Last report return = %d", info->last_return);

	SYSFS_PRINT(len, buf, "Last Input:");
	SYSFS_PRINT(len, buf, "  type = %d", info->last_report.vidwin_rect.eType);
	SYSFS_PRINT(len, buf, "  x, y = %d, %d", info->last_report.vidwin_rect.u16X,
							info->last_report.vidwin_rect.u16Y);
	SYSFS_PRINT(len, buf, "  w, h = %d, %d", info->last_report.vidwin_rect.u16Width,
							info->last_report.vidwin_rect.u16Height);

	SYSFS_PRINT(len, buf, "Last Output:");
	SYSFS_PRINT(len, buf, "  R (min, max, avg) = (%3u, %3u, %3u)",
							info->last_report.pixels_report.u32RcrMin,
							info->last_report.pixels_report.u32RcrMax,
							info->last_report.pixels_report.u32RCrAvg);
	SYSFS_PRINT(len, buf, "  G (min, max, avg) = (%3u, %3u, %3u)",
							info->last_report.pixels_report.u32GYMin,
							info->last_report.pixels_report.u32GYMax,
							info->last_report.pixels_report.u32GYAvg);
	SYSFS_PRINT(len, buf, "  B (min, max, avg) = (%3u, %3u, %3u)",
							info->last_report.pixels_report.u32BcbMin,
							info->last_report.pixels_report.u32BcbMax,
							info->last_report.pixels_report.u32BcbAvg);
	return len;
}

ssize_t window_report_store(struct device *dev,
	struct device_attribute *attr, const char *buf, size_t count)
{
	struct window_report_info *info = &_info;
	struct mtk_tv_kms_context *kms = dev_get_drvdata(dev);
	struct drm_mtk_tv_window_report window_report = info->last_report;
	uint64_t val = 0;

	if (mtk_render_common_parser_cmd_int(buf, "t", &val) == 0)
		window_report.vidwin_rect.eType = val;

	if (mtk_render_common_parser_cmd_int(buf, "x", &val) == 0)
		window_report.vidwin_rect.u16X = val;

	if (mtk_render_common_parser_cmd_int(buf, "y", &val) == 0)
		window_report.vidwin_rect.u16Y = val;

	if (mtk_render_common_parser_cmd_int(buf, "w", &val) == 0)
		window_report.vidwin_rect.u16Width = val;

	if (mtk_render_common_parser_cmd_int(buf, "h", &val) == 0)
		window_report.vidwin_rect.u16Height = val;

	if (mtk_render_common_parser_cmd_int(buf, "d", &val) == 0)
		window_report.vidwin_rect.bDrawEnable = val;

	if (mtk_render_common_parser_cmd_int(buf, "r", &val) == 0)
		window_report.vidwin_rect.u32DrawRcr = val;

	if (mtk_render_common_parser_cmd_int(buf, "g", &val) == 0)
		window_report.vidwin_rect.u32DrawGY = val;

	if (mtk_render_common_parser_cmd_int(buf, "b", &val) == 0)
		window_report.vidwin_rect.u32DrawBcb = val;

	mtk_tv_drm_window_report_read(kms, &window_report);
	return count;
}
