18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) STMicroelectronics SA 2014 48c2ecf20Sopenharmony_ci * Authors: Fabien Dessenne <fabien.dessenne@st.com> for STMicroelectronics. 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#include <linux/delay.h> 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include "bdisp.h" 108c2ecf20Sopenharmony_ci#include "bdisp-filter.h" 118c2ecf20Sopenharmony_ci#include "bdisp-reg.h" 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci/* Max width of the source frame in a single node */ 148c2ecf20Sopenharmony_ci#define MAX_SRC_WIDTH 2048 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci/* Reset & boot poll config */ 178c2ecf20Sopenharmony_ci#define POLL_RST_MAX 500 188c2ecf20Sopenharmony_ci#define POLL_RST_DELAY_MS 2 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_cienum bdisp_target_plan { 218c2ecf20Sopenharmony_ci BDISP_RGB, 228c2ecf20Sopenharmony_ci BDISP_Y, 238c2ecf20Sopenharmony_ci BDISP_CBCR 248c2ecf20Sopenharmony_ci}; 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_cistruct bdisp_op_cfg { 278c2ecf20Sopenharmony_ci bool cconv; /* RGB - YUV conversion */ 288c2ecf20Sopenharmony_ci bool hflip; /* Horizontal flip */ 298c2ecf20Sopenharmony_ci bool vflip; /* Vertical flip */ 308c2ecf20Sopenharmony_ci bool wide; /* Wide (>MAX_SRC_WIDTH) */ 318c2ecf20Sopenharmony_ci bool scale; /* Scale */ 328c2ecf20Sopenharmony_ci u16 h_inc; /* Horizontal increment in 6.10 format */ 338c2ecf20Sopenharmony_ci u16 v_inc; /* Vertical increment in 6.10 format */ 348c2ecf20Sopenharmony_ci bool src_interlaced; /* is the src an interlaced buffer */ 358c2ecf20Sopenharmony_ci u8 src_nbp; /* nb of planes of the src */ 368c2ecf20Sopenharmony_ci bool src_yuv; /* is the src a YUV color format */ 378c2ecf20Sopenharmony_ci bool src_420; /* is the src 4:2:0 chroma subsampled */ 388c2ecf20Sopenharmony_ci u8 dst_nbp; /* nb of planes of the dst */ 398c2ecf20Sopenharmony_ci bool dst_yuv; /* is the dst a YUV color format */ 408c2ecf20Sopenharmony_ci bool dst_420; /* is the dst 4:2:0 chroma subsampled */ 418c2ecf20Sopenharmony_ci}; 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_cistruct bdisp_filter_addr { 448c2ecf20Sopenharmony_ci u16 min; /* Filter min scale factor (6.10 fixed point) */ 458c2ecf20Sopenharmony_ci u16 max; /* Filter max scale factor (6.10 fixed point) */ 468c2ecf20Sopenharmony_ci void *virt; /* Virtual address for filter table */ 478c2ecf20Sopenharmony_ci dma_addr_t paddr; /* Physical address for filter table */ 488c2ecf20Sopenharmony_ci}; 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_cistatic const struct bdisp_filter_h_spec bdisp_h_spec[] = { 518c2ecf20Sopenharmony_ci { 528c2ecf20Sopenharmony_ci .min = 0, 538c2ecf20Sopenharmony_ci .max = 921, 548c2ecf20Sopenharmony_ci .coef = { 558c2ecf20Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 568c2ecf20Sopenharmony_ci 0x00, 0x00, 0xff, 0x07, 0x3d, 0xfc, 0x01, 0x00, 578c2ecf20Sopenharmony_ci 0x00, 0x01, 0xfd, 0x11, 0x36, 0xf9, 0x02, 0x00, 588c2ecf20Sopenharmony_ci 0x00, 0x01, 0xfb, 0x1b, 0x2e, 0xf9, 0x02, 0x00, 598c2ecf20Sopenharmony_ci 0x00, 0x01, 0xf9, 0x26, 0x26, 0xf9, 0x01, 0x00, 608c2ecf20Sopenharmony_ci 0x00, 0x02, 0xf9, 0x30, 0x19, 0xfb, 0x01, 0x00, 618c2ecf20Sopenharmony_ci 0x00, 0x02, 0xf9, 0x39, 0x0e, 0xfd, 0x01, 0x00, 628c2ecf20Sopenharmony_ci 0x00, 0x01, 0xfc, 0x3e, 0x06, 0xff, 0x00, 0x00 638c2ecf20Sopenharmony_ci } 648c2ecf20Sopenharmony_ci }, 658c2ecf20Sopenharmony_ci { 668c2ecf20Sopenharmony_ci .min = 921, 678c2ecf20Sopenharmony_ci .max = 1024, 688c2ecf20Sopenharmony_ci .coef = { 698c2ecf20Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 708c2ecf20Sopenharmony_ci 0xff, 0x03, 0xfd, 0x08, 0x3e, 0xf9, 0x04, 0xfe, 718c2ecf20Sopenharmony_ci 0xfd, 0x06, 0xf8, 0x13, 0x3b, 0xf4, 0x07, 0xfc, 728c2ecf20Sopenharmony_ci 0xfb, 0x08, 0xf5, 0x1f, 0x34, 0xf1, 0x09, 0xfb, 738c2ecf20Sopenharmony_ci 0xfb, 0x09, 0xf2, 0x2b, 0x2a, 0xf1, 0x09, 0xfb, 748c2ecf20Sopenharmony_ci 0xfb, 0x09, 0xf2, 0x35, 0x1e, 0xf4, 0x08, 0xfb, 758c2ecf20Sopenharmony_ci 0xfc, 0x07, 0xf5, 0x3c, 0x12, 0xf7, 0x06, 0xfd, 768c2ecf20Sopenharmony_ci 0xfe, 0x04, 0xfa, 0x3f, 0x07, 0xfc, 0x03, 0xff 778c2ecf20Sopenharmony_ci } 788c2ecf20Sopenharmony_ci }, 798c2ecf20Sopenharmony_ci { 808c2ecf20Sopenharmony_ci .min = 1024, 818c2ecf20Sopenharmony_ci .max = 1126, 828c2ecf20Sopenharmony_ci .coef = { 838c2ecf20Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 848c2ecf20Sopenharmony_ci 0xff, 0x03, 0xfd, 0x08, 0x3e, 0xf9, 0x04, 0xfe, 858c2ecf20Sopenharmony_ci 0xfd, 0x06, 0xf8, 0x13, 0x3b, 0xf4, 0x07, 0xfc, 868c2ecf20Sopenharmony_ci 0xfb, 0x08, 0xf5, 0x1f, 0x34, 0xf1, 0x09, 0xfb, 878c2ecf20Sopenharmony_ci 0xfb, 0x09, 0xf2, 0x2b, 0x2a, 0xf1, 0x09, 0xfb, 888c2ecf20Sopenharmony_ci 0xfb, 0x09, 0xf2, 0x35, 0x1e, 0xf4, 0x08, 0xfb, 898c2ecf20Sopenharmony_ci 0xfc, 0x07, 0xf5, 0x3c, 0x12, 0xf7, 0x06, 0xfd, 908c2ecf20Sopenharmony_ci 0xfe, 0x04, 0xfa, 0x3f, 0x07, 0xfc, 0x03, 0xff 918c2ecf20Sopenharmony_ci } 928c2ecf20Sopenharmony_ci }, 938c2ecf20Sopenharmony_ci { 948c2ecf20Sopenharmony_ci .min = 1126, 958c2ecf20Sopenharmony_ci .max = 1228, 968c2ecf20Sopenharmony_ci .coef = { 978c2ecf20Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 988c2ecf20Sopenharmony_ci 0xff, 0x03, 0xfd, 0x08, 0x3e, 0xf9, 0x04, 0xfe, 998c2ecf20Sopenharmony_ci 0xfd, 0x06, 0xf8, 0x13, 0x3b, 0xf4, 0x07, 0xfc, 1008c2ecf20Sopenharmony_ci 0xfb, 0x08, 0xf5, 0x1f, 0x34, 0xf1, 0x09, 0xfb, 1018c2ecf20Sopenharmony_ci 0xfb, 0x09, 0xf2, 0x2b, 0x2a, 0xf1, 0x09, 0xfb, 1028c2ecf20Sopenharmony_ci 0xfb, 0x09, 0xf2, 0x35, 0x1e, 0xf4, 0x08, 0xfb, 1038c2ecf20Sopenharmony_ci 0xfc, 0x07, 0xf5, 0x3c, 0x12, 0xf7, 0x06, 0xfd, 1048c2ecf20Sopenharmony_ci 0xfe, 0x04, 0xfa, 0x3f, 0x07, 0xfc, 0x03, 0xff 1058c2ecf20Sopenharmony_ci } 1068c2ecf20Sopenharmony_ci }, 1078c2ecf20Sopenharmony_ci { 1088c2ecf20Sopenharmony_ci .min = 1228, 1098c2ecf20Sopenharmony_ci .max = 1331, 1108c2ecf20Sopenharmony_ci .coef = { 1118c2ecf20Sopenharmony_ci 0xfd, 0x04, 0xfc, 0x05, 0x39, 0x05, 0xfc, 0x04, 1128c2ecf20Sopenharmony_ci 0xfc, 0x06, 0xf9, 0x0c, 0x39, 0xfe, 0x00, 0x02, 1138c2ecf20Sopenharmony_ci 0xfb, 0x08, 0xf6, 0x17, 0x35, 0xf9, 0x02, 0x00, 1148c2ecf20Sopenharmony_ci 0xfc, 0x08, 0xf4, 0x20, 0x30, 0xf4, 0x05, 0xff, 1158c2ecf20Sopenharmony_ci 0xfd, 0x07, 0xf4, 0x29, 0x28, 0xf3, 0x07, 0xfd, 1168c2ecf20Sopenharmony_ci 0xff, 0x05, 0xf5, 0x31, 0x1f, 0xf3, 0x08, 0xfc, 1178c2ecf20Sopenharmony_ci 0x00, 0x02, 0xf9, 0x38, 0x14, 0xf6, 0x08, 0xfb, 1188c2ecf20Sopenharmony_ci 0x02, 0x00, 0xff, 0x3a, 0x0b, 0xf8, 0x06, 0xfc 1198c2ecf20Sopenharmony_ci } 1208c2ecf20Sopenharmony_ci }, 1218c2ecf20Sopenharmony_ci { 1228c2ecf20Sopenharmony_ci .min = 1331, 1238c2ecf20Sopenharmony_ci .max = 1433, 1248c2ecf20Sopenharmony_ci .coef = { 1258c2ecf20Sopenharmony_ci 0xfc, 0x06, 0xf9, 0x09, 0x34, 0x09, 0xf9, 0x06, 1268c2ecf20Sopenharmony_ci 0xfd, 0x07, 0xf7, 0x10, 0x32, 0x02, 0xfc, 0x05, 1278c2ecf20Sopenharmony_ci 0xfe, 0x07, 0xf6, 0x17, 0x2f, 0xfc, 0xff, 0x04, 1288c2ecf20Sopenharmony_ci 0xff, 0x06, 0xf5, 0x20, 0x2a, 0xf9, 0x01, 0x02, 1298c2ecf20Sopenharmony_ci 0x00, 0x04, 0xf6, 0x27, 0x25, 0xf6, 0x04, 0x00, 1308c2ecf20Sopenharmony_ci 0x02, 0x01, 0xf9, 0x2d, 0x1d, 0xf5, 0x06, 0xff, 1318c2ecf20Sopenharmony_ci 0x04, 0xff, 0xfd, 0x31, 0x15, 0xf5, 0x07, 0xfe, 1328c2ecf20Sopenharmony_ci 0x05, 0xfc, 0x02, 0x35, 0x0d, 0xf7, 0x07, 0xfd 1338c2ecf20Sopenharmony_ci } 1348c2ecf20Sopenharmony_ci }, 1358c2ecf20Sopenharmony_ci { 1368c2ecf20Sopenharmony_ci .min = 1433, 1378c2ecf20Sopenharmony_ci .max = 1536, 1388c2ecf20Sopenharmony_ci .coef = { 1398c2ecf20Sopenharmony_ci 0xfe, 0x06, 0xf8, 0x0b, 0x30, 0x0b, 0xf8, 0x06, 1408c2ecf20Sopenharmony_ci 0xff, 0x06, 0xf7, 0x12, 0x2d, 0x05, 0xfa, 0x06, 1418c2ecf20Sopenharmony_ci 0x00, 0x04, 0xf6, 0x18, 0x2c, 0x00, 0xfc, 0x06, 1428c2ecf20Sopenharmony_ci 0x01, 0x02, 0xf7, 0x1f, 0x27, 0xfd, 0xff, 0x04, 1438c2ecf20Sopenharmony_ci 0x03, 0x00, 0xf9, 0x24, 0x24, 0xf9, 0x00, 0x03, 1448c2ecf20Sopenharmony_ci 0x04, 0xff, 0xfd, 0x29, 0x1d, 0xf7, 0x02, 0x01, 1458c2ecf20Sopenharmony_ci 0x06, 0xfc, 0x00, 0x2d, 0x17, 0xf6, 0x04, 0x00, 1468c2ecf20Sopenharmony_ci 0x06, 0xfa, 0x05, 0x30, 0x0f, 0xf7, 0x06, 0xff 1478c2ecf20Sopenharmony_ci } 1488c2ecf20Sopenharmony_ci }, 1498c2ecf20Sopenharmony_ci { 1508c2ecf20Sopenharmony_ci .min = 1536, 1518c2ecf20Sopenharmony_ci .max = 2048, 1528c2ecf20Sopenharmony_ci .coef = { 1538c2ecf20Sopenharmony_ci 0x05, 0xfd, 0xfb, 0x13, 0x25, 0x13, 0xfb, 0xfd, 1548c2ecf20Sopenharmony_ci 0x05, 0xfc, 0xfd, 0x17, 0x24, 0x0f, 0xf9, 0xff, 1558c2ecf20Sopenharmony_ci 0x04, 0xfa, 0xff, 0x1b, 0x24, 0x0b, 0xf9, 0x00, 1568c2ecf20Sopenharmony_ci 0x03, 0xf9, 0x01, 0x1f, 0x23, 0x08, 0xf8, 0x01, 1578c2ecf20Sopenharmony_ci 0x02, 0xf9, 0x04, 0x22, 0x20, 0x04, 0xf9, 0x02, 1588c2ecf20Sopenharmony_ci 0x01, 0xf8, 0x08, 0x25, 0x1d, 0x01, 0xf9, 0x03, 1598c2ecf20Sopenharmony_ci 0x00, 0xf9, 0x0c, 0x25, 0x1a, 0xfe, 0xfa, 0x04, 1608c2ecf20Sopenharmony_ci 0xff, 0xf9, 0x10, 0x26, 0x15, 0xfc, 0xfc, 0x05 1618c2ecf20Sopenharmony_ci } 1628c2ecf20Sopenharmony_ci }, 1638c2ecf20Sopenharmony_ci { 1648c2ecf20Sopenharmony_ci .min = 2048, 1658c2ecf20Sopenharmony_ci .max = 3072, 1668c2ecf20Sopenharmony_ci .coef = { 1678c2ecf20Sopenharmony_ci 0xfc, 0xfd, 0x06, 0x13, 0x18, 0x13, 0x06, 0xfd, 1688c2ecf20Sopenharmony_ci 0xfc, 0xfe, 0x08, 0x15, 0x17, 0x12, 0x04, 0xfc, 1698c2ecf20Sopenharmony_ci 0xfb, 0xfe, 0x0a, 0x16, 0x18, 0x10, 0x03, 0xfc, 1708c2ecf20Sopenharmony_ci 0xfb, 0x00, 0x0b, 0x18, 0x17, 0x0f, 0x01, 0xfb, 1718c2ecf20Sopenharmony_ci 0xfb, 0x00, 0x0d, 0x19, 0x17, 0x0d, 0x00, 0xfb, 1728c2ecf20Sopenharmony_ci 0xfb, 0x01, 0x0f, 0x19, 0x16, 0x0b, 0x00, 0xfb, 1738c2ecf20Sopenharmony_ci 0xfc, 0x03, 0x11, 0x19, 0x15, 0x09, 0xfe, 0xfb, 1748c2ecf20Sopenharmony_ci 0xfc, 0x04, 0x12, 0x1a, 0x12, 0x08, 0xfe, 0xfc 1758c2ecf20Sopenharmony_ci } 1768c2ecf20Sopenharmony_ci }, 1778c2ecf20Sopenharmony_ci { 1788c2ecf20Sopenharmony_ci .min = 3072, 1798c2ecf20Sopenharmony_ci .max = 4096, 1808c2ecf20Sopenharmony_ci .coef = { 1818c2ecf20Sopenharmony_ci 0xfe, 0x02, 0x09, 0x0f, 0x0e, 0x0f, 0x09, 0x02, 1828c2ecf20Sopenharmony_ci 0xff, 0x02, 0x09, 0x0f, 0x10, 0x0e, 0x08, 0x01, 1838c2ecf20Sopenharmony_ci 0xff, 0x03, 0x0a, 0x10, 0x10, 0x0d, 0x07, 0x00, 1848c2ecf20Sopenharmony_ci 0x00, 0x04, 0x0b, 0x10, 0x0f, 0x0c, 0x06, 0x00, 1858c2ecf20Sopenharmony_ci 0x00, 0x05, 0x0c, 0x10, 0x0e, 0x0c, 0x05, 0x00, 1868c2ecf20Sopenharmony_ci 0x00, 0x06, 0x0c, 0x11, 0x0e, 0x0b, 0x04, 0x00, 1878c2ecf20Sopenharmony_ci 0x00, 0x07, 0x0d, 0x11, 0x0f, 0x0a, 0x03, 0xff, 1888c2ecf20Sopenharmony_ci 0x01, 0x08, 0x0e, 0x11, 0x0e, 0x09, 0x02, 0xff 1898c2ecf20Sopenharmony_ci } 1908c2ecf20Sopenharmony_ci }, 1918c2ecf20Sopenharmony_ci { 1928c2ecf20Sopenharmony_ci .min = 4096, 1938c2ecf20Sopenharmony_ci .max = 5120, 1948c2ecf20Sopenharmony_ci .coef = { 1958c2ecf20Sopenharmony_ci 0x00, 0x04, 0x09, 0x0c, 0x0e, 0x0c, 0x09, 0x04, 1968c2ecf20Sopenharmony_ci 0x01, 0x05, 0x09, 0x0c, 0x0d, 0x0c, 0x08, 0x04, 1978c2ecf20Sopenharmony_ci 0x01, 0x05, 0x0a, 0x0c, 0x0e, 0x0b, 0x08, 0x03, 1988c2ecf20Sopenharmony_ci 0x02, 0x06, 0x0a, 0x0d, 0x0c, 0x0b, 0x07, 0x03, 1998c2ecf20Sopenharmony_ci 0x02, 0x07, 0x0a, 0x0d, 0x0d, 0x0a, 0x07, 0x02, 2008c2ecf20Sopenharmony_ci 0x03, 0x07, 0x0b, 0x0d, 0x0c, 0x0a, 0x06, 0x02, 2018c2ecf20Sopenharmony_ci 0x03, 0x08, 0x0b, 0x0d, 0x0d, 0x0a, 0x05, 0x01, 2028c2ecf20Sopenharmony_ci 0x04, 0x08, 0x0c, 0x0d, 0x0c, 0x09, 0x05, 0x01 2038c2ecf20Sopenharmony_ci } 2048c2ecf20Sopenharmony_ci }, 2058c2ecf20Sopenharmony_ci { 2068c2ecf20Sopenharmony_ci .min = 5120, 2078c2ecf20Sopenharmony_ci .max = 65535, 2088c2ecf20Sopenharmony_ci .coef = { 2098c2ecf20Sopenharmony_ci 0x03, 0x06, 0x09, 0x0b, 0x09, 0x0b, 0x09, 0x06, 2108c2ecf20Sopenharmony_ci 0x03, 0x06, 0x09, 0x0b, 0x0c, 0x0a, 0x08, 0x05, 2118c2ecf20Sopenharmony_ci 0x03, 0x06, 0x09, 0x0b, 0x0c, 0x0a, 0x08, 0x05, 2128c2ecf20Sopenharmony_ci 0x04, 0x07, 0x09, 0x0b, 0x0b, 0x0a, 0x08, 0x04, 2138c2ecf20Sopenharmony_ci 0x04, 0x07, 0x0a, 0x0b, 0x0b, 0x0a, 0x07, 0x04, 2148c2ecf20Sopenharmony_ci 0x04, 0x08, 0x0a, 0x0b, 0x0b, 0x09, 0x07, 0x04, 2158c2ecf20Sopenharmony_ci 0x05, 0x08, 0x0a, 0x0b, 0x0c, 0x09, 0x06, 0x03, 2168c2ecf20Sopenharmony_ci 0x05, 0x08, 0x0a, 0x0b, 0x0c, 0x09, 0x06, 0x03 2178c2ecf20Sopenharmony_ci } 2188c2ecf20Sopenharmony_ci } 2198c2ecf20Sopenharmony_ci}; 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_ci#define NB_H_FILTER ARRAY_SIZE(bdisp_h_spec) 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_cistatic const struct bdisp_filter_v_spec bdisp_v_spec[] = { 2258c2ecf20Sopenharmony_ci { 2268c2ecf20Sopenharmony_ci .min = 0, 2278c2ecf20Sopenharmony_ci .max = 1024, 2288c2ecf20Sopenharmony_ci .coef = { 2298c2ecf20Sopenharmony_ci 0x00, 0x00, 0x40, 0x00, 0x00, 2308c2ecf20Sopenharmony_ci 0x00, 0x06, 0x3d, 0xfd, 0x00, 2318c2ecf20Sopenharmony_ci 0xfe, 0x0f, 0x38, 0xfb, 0x00, 2328c2ecf20Sopenharmony_ci 0xfd, 0x19, 0x2f, 0xfb, 0x00, 2338c2ecf20Sopenharmony_ci 0xfc, 0x24, 0x24, 0xfc, 0x00, 2348c2ecf20Sopenharmony_ci 0xfb, 0x2f, 0x19, 0xfd, 0x00, 2358c2ecf20Sopenharmony_ci 0xfb, 0x38, 0x0f, 0xfe, 0x00, 2368c2ecf20Sopenharmony_ci 0xfd, 0x3d, 0x06, 0x00, 0x00 2378c2ecf20Sopenharmony_ci } 2388c2ecf20Sopenharmony_ci }, 2398c2ecf20Sopenharmony_ci { 2408c2ecf20Sopenharmony_ci .min = 1024, 2418c2ecf20Sopenharmony_ci .max = 1331, 2428c2ecf20Sopenharmony_ci .coef = { 2438c2ecf20Sopenharmony_ci 0xfc, 0x05, 0x3e, 0x05, 0xfc, 2448c2ecf20Sopenharmony_ci 0xf8, 0x0e, 0x3b, 0xff, 0x00, 2458c2ecf20Sopenharmony_ci 0xf5, 0x18, 0x38, 0xf9, 0x02, 2468c2ecf20Sopenharmony_ci 0xf4, 0x21, 0x31, 0xf5, 0x05, 2478c2ecf20Sopenharmony_ci 0xf4, 0x2a, 0x27, 0xf4, 0x07, 2488c2ecf20Sopenharmony_ci 0xf6, 0x30, 0x1e, 0xf4, 0x08, 2498c2ecf20Sopenharmony_ci 0xf9, 0x35, 0x15, 0xf6, 0x07, 2508c2ecf20Sopenharmony_ci 0xff, 0x37, 0x0b, 0xf9, 0x06 2518c2ecf20Sopenharmony_ci } 2528c2ecf20Sopenharmony_ci }, 2538c2ecf20Sopenharmony_ci { 2548c2ecf20Sopenharmony_ci .min = 1331, 2558c2ecf20Sopenharmony_ci .max = 1433, 2568c2ecf20Sopenharmony_ci .coef = { 2578c2ecf20Sopenharmony_ci 0xf8, 0x0a, 0x3c, 0x0a, 0xf8, 2588c2ecf20Sopenharmony_ci 0xf6, 0x12, 0x3b, 0x02, 0xfb, 2598c2ecf20Sopenharmony_ci 0xf4, 0x1b, 0x35, 0xfd, 0xff, 2608c2ecf20Sopenharmony_ci 0xf4, 0x23, 0x30, 0xf8, 0x01, 2618c2ecf20Sopenharmony_ci 0xf6, 0x29, 0x27, 0xf6, 0x04, 2628c2ecf20Sopenharmony_ci 0xf9, 0x2e, 0x1e, 0xf5, 0x06, 2638c2ecf20Sopenharmony_ci 0xfd, 0x31, 0x16, 0xf6, 0x06, 2648c2ecf20Sopenharmony_ci 0x02, 0x32, 0x0d, 0xf8, 0x07 2658c2ecf20Sopenharmony_ci } 2668c2ecf20Sopenharmony_ci }, 2678c2ecf20Sopenharmony_ci { 2688c2ecf20Sopenharmony_ci .min = 1433, 2698c2ecf20Sopenharmony_ci .max = 1536, 2708c2ecf20Sopenharmony_ci .coef = { 2718c2ecf20Sopenharmony_ci 0xf6, 0x0e, 0x38, 0x0e, 0xf6, 2728c2ecf20Sopenharmony_ci 0xf5, 0x15, 0x38, 0x06, 0xf8, 2738c2ecf20Sopenharmony_ci 0xf5, 0x1d, 0x33, 0x00, 0xfb, 2748c2ecf20Sopenharmony_ci 0xf6, 0x23, 0x2d, 0xfc, 0xfe, 2758c2ecf20Sopenharmony_ci 0xf9, 0x28, 0x26, 0xf9, 0x00, 2768c2ecf20Sopenharmony_ci 0xfc, 0x2c, 0x1e, 0xf7, 0x03, 2778c2ecf20Sopenharmony_ci 0x00, 0x2e, 0x18, 0xf6, 0x04, 2788c2ecf20Sopenharmony_ci 0x05, 0x2e, 0x11, 0xf7, 0x05 2798c2ecf20Sopenharmony_ci } 2808c2ecf20Sopenharmony_ci }, 2818c2ecf20Sopenharmony_ci { 2828c2ecf20Sopenharmony_ci .min = 1536, 2838c2ecf20Sopenharmony_ci .max = 2048, 2848c2ecf20Sopenharmony_ci .coef = { 2858c2ecf20Sopenharmony_ci 0xfb, 0x13, 0x24, 0x13, 0xfb, 2868c2ecf20Sopenharmony_ci 0xfd, 0x17, 0x23, 0x0f, 0xfa, 2878c2ecf20Sopenharmony_ci 0xff, 0x1a, 0x23, 0x0b, 0xf9, 2888c2ecf20Sopenharmony_ci 0x01, 0x1d, 0x22, 0x07, 0xf9, 2898c2ecf20Sopenharmony_ci 0x04, 0x20, 0x1f, 0x04, 0xf9, 2908c2ecf20Sopenharmony_ci 0x07, 0x22, 0x1c, 0x01, 0xfa, 2918c2ecf20Sopenharmony_ci 0x0b, 0x24, 0x17, 0xff, 0xfb, 2928c2ecf20Sopenharmony_ci 0x0f, 0x24, 0x14, 0xfd, 0xfc 2938c2ecf20Sopenharmony_ci } 2948c2ecf20Sopenharmony_ci }, 2958c2ecf20Sopenharmony_ci { 2968c2ecf20Sopenharmony_ci .min = 2048, 2978c2ecf20Sopenharmony_ci .max = 3072, 2988c2ecf20Sopenharmony_ci .coef = { 2998c2ecf20Sopenharmony_ci 0x05, 0x10, 0x16, 0x10, 0x05, 3008c2ecf20Sopenharmony_ci 0x06, 0x11, 0x16, 0x0f, 0x04, 3018c2ecf20Sopenharmony_ci 0x08, 0x13, 0x15, 0x0e, 0x02, 3028c2ecf20Sopenharmony_ci 0x09, 0x14, 0x16, 0x0c, 0x01, 3038c2ecf20Sopenharmony_ci 0x0b, 0x15, 0x15, 0x0b, 0x00, 3048c2ecf20Sopenharmony_ci 0x0d, 0x16, 0x13, 0x0a, 0x00, 3058c2ecf20Sopenharmony_ci 0x0f, 0x17, 0x13, 0x08, 0xff, 3068c2ecf20Sopenharmony_ci 0x11, 0x18, 0x12, 0x07, 0xfe 3078c2ecf20Sopenharmony_ci } 3088c2ecf20Sopenharmony_ci }, 3098c2ecf20Sopenharmony_ci { 3108c2ecf20Sopenharmony_ci .min = 3072, 3118c2ecf20Sopenharmony_ci .max = 4096, 3128c2ecf20Sopenharmony_ci .coef = { 3138c2ecf20Sopenharmony_ci 0x09, 0x0f, 0x10, 0x0f, 0x09, 3148c2ecf20Sopenharmony_ci 0x09, 0x0f, 0x12, 0x0e, 0x08, 3158c2ecf20Sopenharmony_ci 0x0a, 0x10, 0x11, 0x0e, 0x07, 3168c2ecf20Sopenharmony_ci 0x0b, 0x11, 0x11, 0x0d, 0x06, 3178c2ecf20Sopenharmony_ci 0x0c, 0x11, 0x12, 0x0c, 0x05, 3188c2ecf20Sopenharmony_ci 0x0d, 0x12, 0x11, 0x0c, 0x04, 3198c2ecf20Sopenharmony_ci 0x0e, 0x12, 0x11, 0x0b, 0x04, 3208c2ecf20Sopenharmony_ci 0x0f, 0x13, 0x11, 0x0a, 0x03 3218c2ecf20Sopenharmony_ci } 3228c2ecf20Sopenharmony_ci }, 3238c2ecf20Sopenharmony_ci { 3248c2ecf20Sopenharmony_ci .min = 4096, 3258c2ecf20Sopenharmony_ci .max = 5120, 3268c2ecf20Sopenharmony_ci .coef = { 3278c2ecf20Sopenharmony_ci 0x0a, 0x0e, 0x10, 0x0e, 0x0a, 3288c2ecf20Sopenharmony_ci 0x0b, 0x0e, 0x0f, 0x0e, 0x0a, 3298c2ecf20Sopenharmony_ci 0x0b, 0x0f, 0x10, 0x0d, 0x09, 3308c2ecf20Sopenharmony_ci 0x0c, 0x0f, 0x10, 0x0d, 0x08, 3318c2ecf20Sopenharmony_ci 0x0d, 0x0f, 0x0f, 0x0d, 0x08, 3328c2ecf20Sopenharmony_ci 0x0d, 0x10, 0x10, 0x0c, 0x07, 3338c2ecf20Sopenharmony_ci 0x0e, 0x10, 0x0f, 0x0c, 0x07, 3348c2ecf20Sopenharmony_ci 0x0f, 0x10, 0x10, 0x0b, 0x06 3358c2ecf20Sopenharmony_ci } 3368c2ecf20Sopenharmony_ci }, 3378c2ecf20Sopenharmony_ci { 3388c2ecf20Sopenharmony_ci .min = 5120, 3398c2ecf20Sopenharmony_ci .max = 65535, 3408c2ecf20Sopenharmony_ci .coef = { 3418c2ecf20Sopenharmony_ci 0x0b, 0x0e, 0x0e, 0x0e, 0x0b, 3428c2ecf20Sopenharmony_ci 0x0b, 0x0e, 0x0f, 0x0d, 0x0b, 3438c2ecf20Sopenharmony_ci 0x0c, 0x0e, 0x0f, 0x0d, 0x0a, 3448c2ecf20Sopenharmony_ci 0x0c, 0x0e, 0x0f, 0x0d, 0x0a, 3458c2ecf20Sopenharmony_ci 0x0d, 0x0f, 0x0e, 0x0d, 0x09, 3468c2ecf20Sopenharmony_ci 0x0d, 0x0f, 0x0f, 0x0c, 0x09, 3478c2ecf20Sopenharmony_ci 0x0e, 0x0f, 0x0e, 0x0c, 0x09, 3488c2ecf20Sopenharmony_ci 0x0e, 0x0f, 0x0f, 0x0c, 0x08 3498c2ecf20Sopenharmony_ci } 3508c2ecf20Sopenharmony_ci } 3518c2ecf20Sopenharmony_ci}; 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ci#define NB_V_FILTER ARRAY_SIZE(bdisp_v_spec) 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_cistatic struct bdisp_filter_addr bdisp_h_filter[NB_H_FILTER]; 3568c2ecf20Sopenharmony_cistatic struct bdisp_filter_addr bdisp_v_filter[NB_V_FILTER]; 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_ci/** 3598c2ecf20Sopenharmony_ci * bdisp_hw_reset 3608c2ecf20Sopenharmony_ci * @bdisp: bdisp entity 3618c2ecf20Sopenharmony_ci * 3628c2ecf20Sopenharmony_ci * Resets HW 3638c2ecf20Sopenharmony_ci * 3648c2ecf20Sopenharmony_ci * RETURNS: 3658c2ecf20Sopenharmony_ci * 0 on success. 3668c2ecf20Sopenharmony_ci */ 3678c2ecf20Sopenharmony_ciint bdisp_hw_reset(struct bdisp_dev *bdisp) 3688c2ecf20Sopenharmony_ci{ 3698c2ecf20Sopenharmony_ci unsigned int i; 3708c2ecf20Sopenharmony_ci 3718c2ecf20Sopenharmony_ci dev_dbg(bdisp->dev, "%s\n", __func__); 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci /* Mask Interrupt */ 3748c2ecf20Sopenharmony_ci writel(0, bdisp->regs + BLT_ITM0); 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_ci /* Reset */ 3778c2ecf20Sopenharmony_ci writel(readl(bdisp->regs + BLT_CTL) | BLT_CTL_RESET, 3788c2ecf20Sopenharmony_ci bdisp->regs + BLT_CTL); 3798c2ecf20Sopenharmony_ci writel(0, bdisp->regs + BLT_CTL); 3808c2ecf20Sopenharmony_ci 3818c2ecf20Sopenharmony_ci /* Wait for reset done */ 3828c2ecf20Sopenharmony_ci for (i = 0; i < POLL_RST_MAX; i++) { 3838c2ecf20Sopenharmony_ci if (readl(bdisp->regs + BLT_STA1) & BLT_STA1_IDLE) 3848c2ecf20Sopenharmony_ci break; 3858c2ecf20Sopenharmony_ci udelay(POLL_RST_DELAY_MS * 1000); 3868c2ecf20Sopenharmony_ci } 3878c2ecf20Sopenharmony_ci if (i == POLL_RST_MAX) 3888c2ecf20Sopenharmony_ci dev_err(bdisp->dev, "Reset timeout\n"); 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_ci return (i == POLL_RST_MAX) ? -EAGAIN : 0; 3918c2ecf20Sopenharmony_ci} 3928c2ecf20Sopenharmony_ci 3938c2ecf20Sopenharmony_ci/** 3948c2ecf20Sopenharmony_ci * bdisp_hw_get_and_clear_irq 3958c2ecf20Sopenharmony_ci * @bdisp: bdisp entity 3968c2ecf20Sopenharmony_ci * 3978c2ecf20Sopenharmony_ci * Read then reset interrupt status 3988c2ecf20Sopenharmony_ci * 3998c2ecf20Sopenharmony_ci * RETURNS: 4008c2ecf20Sopenharmony_ci * 0 if expected interrupt was raised. 4018c2ecf20Sopenharmony_ci */ 4028c2ecf20Sopenharmony_ciint bdisp_hw_get_and_clear_irq(struct bdisp_dev *bdisp) 4038c2ecf20Sopenharmony_ci{ 4048c2ecf20Sopenharmony_ci u32 its; 4058c2ecf20Sopenharmony_ci 4068c2ecf20Sopenharmony_ci its = readl(bdisp->regs + BLT_ITS); 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_ci /* Check for the only expected IT: LastNode of AQ1 */ 4098c2ecf20Sopenharmony_ci if (!(its & BLT_ITS_AQ1_LNA)) { 4108c2ecf20Sopenharmony_ci dev_dbg(bdisp->dev, "Unexpected IT status: 0x%08X\n", its); 4118c2ecf20Sopenharmony_ci writel(its, bdisp->regs + BLT_ITS); 4128c2ecf20Sopenharmony_ci return -1; 4138c2ecf20Sopenharmony_ci } 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_ci /* Clear and mask */ 4168c2ecf20Sopenharmony_ci writel(its, bdisp->regs + BLT_ITS); 4178c2ecf20Sopenharmony_ci writel(0, bdisp->regs + BLT_ITM0); 4188c2ecf20Sopenharmony_ci 4198c2ecf20Sopenharmony_ci return 0; 4208c2ecf20Sopenharmony_ci} 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_ci/** 4238c2ecf20Sopenharmony_ci * bdisp_hw_free_nodes 4248c2ecf20Sopenharmony_ci * @ctx: bdisp context 4258c2ecf20Sopenharmony_ci * 4268c2ecf20Sopenharmony_ci * Free node memory 4278c2ecf20Sopenharmony_ci * 4288c2ecf20Sopenharmony_ci * RETURNS: 4298c2ecf20Sopenharmony_ci * None 4308c2ecf20Sopenharmony_ci */ 4318c2ecf20Sopenharmony_civoid bdisp_hw_free_nodes(struct bdisp_ctx *ctx) 4328c2ecf20Sopenharmony_ci{ 4338c2ecf20Sopenharmony_ci if (ctx && ctx->node[0]) 4348c2ecf20Sopenharmony_ci dma_free_attrs(ctx->bdisp_dev->dev, 4358c2ecf20Sopenharmony_ci sizeof(struct bdisp_node) * MAX_NB_NODE, 4368c2ecf20Sopenharmony_ci ctx->node[0], ctx->node_paddr[0], 4378c2ecf20Sopenharmony_ci DMA_ATTR_WRITE_COMBINE); 4388c2ecf20Sopenharmony_ci} 4398c2ecf20Sopenharmony_ci 4408c2ecf20Sopenharmony_ci/** 4418c2ecf20Sopenharmony_ci * bdisp_hw_alloc_nodes 4428c2ecf20Sopenharmony_ci * @ctx: bdisp context 4438c2ecf20Sopenharmony_ci * 4448c2ecf20Sopenharmony_ci * Allocate dma memory for nodes 4458c2ecf20Sopenharmony_ci * 4468c2ecf20Sopenharmony_ci * RETURNS: 4478c2ecf20Sopenharmony_ci * 0 on success 4488c2ecf20Sopenharmony_ci */ 4498c2ecf20Sopenharmony_ciint bdisp_hw_alloc_nodes(struct bdisp_ctx *ctx) 4508c2ecf20Sopenharmony_ci{ 4518c2ecf20Sopenharmony_ci struct device *dev = ctx->bdisp_dev->dev; 4528c2ecf20Sopenharmony_ci unsigned int i, node_size = sizeof(struct bdisp_node); 4538c2ecf20Sopenharmony_ci void *base; 4548c2ecf20Sopenharmony_ci dma_addr_t paddr; 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_ci /* Allocate all the nodes within a single memory page */ 4578c2ecf20Sopenharmony_ci base = dma_alloc_attrs(dev, node_size * MAX_NB_NODE, &paddr, 4588c2ecf20Sopenharmony_ci GFP_KERNEL, DMA_ATTR_WRITE_COMBINE); 4598c2ecf20Sopenharmony_ci if (!base) { 4608c2ecf20Sopenharmony_ci dev_err(dev, "%s no mem\n", __func__); 4618c2ecf20Sopenharmony_ci return -ENOMEM; 4628c2ecf20Sopenharmony_ci } 4638c2ecf20Sopenharmony_ci 4648c2ecf20Sopenharmony_ci memset(base, 0, node_size * MAX_NB_NODE); 4658c2ecf20Sopenharmony_ci 4668c2ecf20Sopenharmony_ci for (i = 0; i < MAX_NB_NODE; i++) { 4678c2ecf20Sopenharmony_ci ctx->node[i] = base; 4688c2ecf20Sopenharmony_ci ctx->node_paddr[i] = paddr; 4698c2ecf20Sopenharmony_ci dev_dbg(dev, "node[%d]=0x%p (paddr=%pad)\n", i, ctx->node[i], 4708c2ecf20Sopenharmony_ci &paddr); 4718c2ecf20Sopenharmony_ci base += node_size; 4728c2ecf20Sopenharmony_ci paddr += node_size; 4738c2ecf20Sopenharmony_ci } 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_ci return 0; 4768c2ecf20Sopenharmony_ci} 4778c2ecf20Sopenharmony_ci 4788c2ecf20Sopenharmony_ci/** 4798c2ecf20Sopenharmony_ci * bdisp_hw_free_filters 4808c2ecf20Sopenharmony_ci * @dev: device 4818c2ecf20Sopenharmony_ci * 4828c2ecf20Sopenharmony_ci * Free filters memory 4838c2ecf20Sopenharmony_ci * 4848c2ecf20Sopenharmony_ci * RETURNS: 4858c2ecf20Sopenharmony_ci * None 4868c2ecf20Sopenharmony_ci */ 4878c2ecf20Sopenharmony_civoid bdisp_hw_free_filters(struct device *dev) 4888c2ecf20Sopenharmony_ci{ 4898c2ecf20Sopenharmony_ci int size = (BDISP_HF_NB * NB_H_FILTER) + (BDISP_VF_NB * NB_V_FILTER); 4908c2ecf20Sopenharmony_ci 4918c2ecf20Sopenharmony_ci if (bdisp_h_filter[0].virt) 4928c2ecf20Sopenharmony_ci dma_free_attrs(dev, size, bdisp_h_filter[0].virt, 4938c2ecf20Sopenharmony_ci bdisp_h_filter[0].paddr, DMA_ATTR_WRITE_COMBINE); 4948c2ecf20Sopenharmony_ci} 4958c2ecf20Sopenharmony_ci 4968c2ecf20Sopenharmony_ci/** 4978c2ecf20Sopenharmony_ci * bdisp_hw_alloc_filters 4988c2ecf20Sopenharmony_ci * @dev: device 4998c2ecf20Sopenharmony_ci * 5008c2ecf20Sopenharmony_ci * Allocate dma memory for filters 5018c2ecf20Sopenharmony_ci * 5028c2ecf20Sopenharmony_ci * RETURNS: 5038c2ecf20Sopenharmony_ci * 0 on success 5048c2ecf20Sopenharmony_ci */ 5058c2ecf20Sopenharmony_ciint bdisp_hw_alloc_filters(struct device *dev) 5068c2ecf20Sopenharmony_ci{ 5078c2ecf20Sopenharmony_ci unsigned int i, size; 5088c2ecf20Sopenharmony_ci void *base; 5098c2ecf20Sopenharmony_ci dma_addr_t paddr; 5108c2ecf20Sopenharmony_ci 5118c2ecf20Sopenharmony_ci /* Allocate all the filters within a single memory page */ 5128c2ecf20Sopenharmony_ci size = (BDISP_HF_NB * NB_H_FILTER) + (BDISP_VF_NB * NB_V_FILTER); 5138c2ecf20Sopenharmony_ci base = dma_alloc_attrs(dev, size, &paddr, GFP_KERNEL, 5148c2ecf20Sopenharmony_ci DMA_ATTR_WRITE_COMBINE); 5158c2ecf20Sopenharmony_ci if (!base) 5168c2ecf20Sopenharmony_ci return -ENOMEM; 5178c2ecf20Sopenharmony_ci 5188c2ecf20Sopenharmony_ci /* Setup filter addresses */ 5198c2ecf20Sopenharmony_ci for (i = 0; i < NB_H_FILTER; i++) { 5208c2ecf20Sopenharmony_ci bdisp_h_filter[i].min = bdisp_h_spec[i].min; 5218c2ecf20Sopenharmony_ci bdisp_h_filter[i].max = bdisp_h_spec[i].max; 5228c2ecf20Sopenharmony_ci memcpy(base, bdisp_h_spec[i].coef, BDISP_HF_NB); 5238c2ecf20Sopenharmony_ci bdisp_h_filter[i].virt = base; 5248c2ecf20Sopenharmony_ci bdisp_h_filter[i].paddr = paddr; 5258c2ecf20Sopenharmony_ci base += BDISP_HF_NB; 5268c2ecf20Sopenharmony_ci paddr += BDISP_HF_NB; 5278c2ecf20Sopenharmony_ci } 5288c2ecf20Sopenharmony_ci 5298c2ecf20Sopenharmony_ci for (i = 0; i < NB_V_FILTER; i++) { 5308c2ecf20Sopenharmony_ci bdisp_v_filter[i].min = bdisp_v_spec[i].min; 5318c2ecf20Sopenharmony_ci bdisp_v_filter[i].max = bdisp_v_spec[i].max; 5328c2ecf20Sopenharmony_ci memcpy(base, bdisp_v_spec[i].coef, BDISP_VF_NB); 5338c2ecf20Sopenharmony_ci bdisp_v_filter[i].virt = base; 5348c2ecf20Sopenharmony_ci bdisp_v_filter[i].paddr = paddr; 5358c2ecf20Sopenharmony_ci base += BDISP_VF_NB; 5368c2ecf20Sopenharmony_ci paddr += BDISP_VF_NB; 5378c2ecf20Sopenharmony_ci } 5388c2ecf20Sopenharmony_ci 5398c2ecf20Sopenharmony_ci return 0; 5408c2ecf20Sopenharmony_ci} 5418c2ecf20Sopenharmony_ci 5428c2ecf20Sopenharmony_ci/** 5438c2ecf20Sopenharmony_ci * bdisp_hw_get_hf_addr 5448c2ecf20Sopenharmony_ci * @inc: resize increment 5458c2ecf20Sopenharmony_ci * 5468c2ecf20Sopenharmony_ci * Find the horizontal filter table that fits the resize increment 5478c2ecf20Sopenharmony_ci * 5488c2ecf20Sopenharmony_ci * RETURNS: 5498c2ecf20Sopenharmony_ci * table physical address 5508c2ecf20Sopenharmony_ci */ 5518c2ecf20Sopenharmony_cistatic dma_addr_t bdisp_hw_get_hf_addr(u16 inc) 5528c2ecf20Sopenharmony_ci{ 5538c2ecf20Sopenharmony_ci unsigned int i; 5548c2ecf20Sopenharmony_ci 5558c2ecf20Sopenharmony_ci for (i = NB_H_FILTER - 1; i > 0; i--) 5568c2ecf20Sopenharmony_ci if ((bdisp_h_filter[i].min < inc) && 5578c2ecf20Sopenharmony_ci (inc <= bdisp_h_filter[i].max)) 5588c2ecf20Sopenharmony_ci break; 5598c2ecf20Sopenharmony_ci 5608c2ecf20Sopenharmony_ci return bdisp_h_filter[i].paddr; 5618c2ecf20Sopenharmony_ci} 5628c2ecf20Sopenharmony_ci 5638c2ecf20Sopenharmony_ci/** 5648c2ecf20Sopenharmony_ci * bdisp_hw_get_vf_addr 5658c2ecf20Sopenharmony_ci * @inc: resize increment 5668c2ecf20Sopenharmony_ci * 5678c2ecf20Sopenharmony_ci * Find the vertical filter table that fits the resize increment 5688c2ecf20Sopenharmony_ci * 5698c2ecf20Sopenharmony_ci * RETURNS: 5708c2ecf20Sopenharmony_ci * table physical address 5718c2ecf20Sopenharmony_ci */ 5728c2ecf20Sopenharmony_cistatic dma_addr_t bdisp_hw_get_vf_addr(u16 inc) 5738c2ecf20Sopenharmony_ci{ 5748c2ecf20Sopenharmony_ci unsigned int i; 5758c2ecf20Sopenharmony_ci 5768c2ecf20Sopenharmony_ci for (i = NB_V_FILTER - 1; i > 0; i--) 5778c2ecf20Sopenharmony_ci if ((bdisp_v_filter[i].min < inc) && 5788c2ecf20Sopenharmony_ci (inc <= bdisp_v_filter[i].max)) 5798c2ecf20Sopenharmony_ci break; 5808c2ecf20Sopenharmony_ci 5818c2ecf20Sopenharmony_ci return bdisp_v_filter[i].paddr; 5828c2ecf20Sopenharmony_ci} 5838c2ecf20Sopenharmony_ci 5848c2ecf20Sopenharmony_ci/** 5858c2ecf20Sopenharmony_ci * bdisp_hw_get_inc 5868c2ecf20Sopenharmony_ci * @from: input size 5878c2ecf20Sopenharmony_ci * @to: output size 5888c2ecf20Sopenharmony_ci * @inc: resize increment in 6.10 format 5898c2ecf20Sopenharmony_ci * 5908c2ecf20Sopenharmony_ci * Computes the increment (inverse of scale) in 6.10 format 5918c2ecf20Sopenharmony_ci * 5928c2ecf20Sopenharmony_ci * RETURNS: 5938c2ecf20Sopenharmony_ci * 0 on success 5948c2ecf20Sopenharmony_ci */ 5958c2ecf20Sopenharmony_cistatic int bdisp_hw_get_inc(u32 from, u32 to, u16 *inc) 5968c2ecf20Sopenharmony_ci{ 5978c2ecf20Sopenharmony_ci u32 tmp; 5988c2ecf20Sopenharmony_ci 5998c2ecf20Sopenharmony_ci if (!to) 6008c2ecf20Sopenharmony_ci return -EINVAL; 6018c2ecf20Sopenharmony_ci 6028c2ecf20Sopenharmony_ci if (to == from) { 6038c2ecf20Sopenharmony_ci *inc = 1 << 10; 6048c2ecf20Sopenharmony_ci return 0; 6058c2ecf20Sopenharmony_ci } 6068c2ecf20Sopenharmony_ci 6078c2ecf20Sopenharmony_ci tmp = (from << 10) / to; 6088c2ecf20Sopenharmony_ci if ((tmp > 0xFFFF) || (!tmp)) 6098c2ecf20Sopenharmony_ci /* overflow (downscale x 63) or too small (upscale x 1024) */ 6108c2ecf20Sopenharmony_ci return -EINVAL; 6118c2ecf20Sopenharmony_ci 6128c2ecf20Sopenharmony_ci *inc = (u16)tmp; 6138c2ecf20Sopenharmony_ci 6148c2ecf20Sopenharmony_ci return 0; 6158c2ecf20Sopenharmony_ci} 6168c2ecf20Sopenharmony_ci 6178c2ecf20Sopenharmony_ci/** 6188c2ecf20Sopenharmony_ci * bdisp_hw_get_hv_inc 6198c2ecf20Sopenharmony_ci * @ctx: device context 6208c2ecf20Sopenharmony_ci * @h_inc: horizontal increment 6218c2ecf20Sopenharmony_ci * @v_inc: vertical increment 6228c2ecf20Sopenharmony_ci * 6238c2ecf20Sopenharmony_ci * Computes the horizontal & vertical increments (inverse of scale) 6248c2ecf20Sopenharmony_ci * 6258c2ecf20Sopenharmony_ci * RETURNS: 6268c2ecf20Sopenharmony_ci * 0 on success 6278c2ecf20Sopenharmony_ci */ 6288c2ecf20Sopenharmony_cistatic int bdisp_hw_get_hv_inc(struct bdisp_ctx *ctx, u16 *h_inc, u16 *v_inc) 6298c2ecf20Sopenharmony_ci{ 6308c2ecf20Sopenharmony_ci u32 src_w, src_h, dst_w, dst_h; 6318c2ecf20Sopenharmony_ci 6328c2ecf20Sopenharmony_ci src_w = ctx->src.crop.width; 6338c2ecf20Sopenharmony_ci src_h = ctx->src.crop.height; 6348c2ecf20Sopenharmony_ci dst_w = ctx->dst.crop.width; 6358c2ecf20Sopenharmony_ci dst_h = ctx->dst.crop.height; 6368c2ecf20Sopenharmony_ci 6378c2ecf20Sopenharmony_ci if (bdisp_hw_get_inc(src_w, dst_w, h_inc) || 6388c2ecf20Sopenharmony_ci bdisp_hw_get_inc(src_h, dst_h, v_inc)) { 6398c2ecf20Sopenharmony_ci dev_err(ctx->bdisp_dev->dev, 6408c2ecf20Sopenharmony_ci "scale factors failed (%dx%d)->(%dx%d)\n", 6418c2ecf20Sopenharmony_ci src_w, src_h, dst_w, dst_h); 6428c2ecf20Sopenharmony_ci return -EINVAL; 6438c2ecf20Sopenharmony_ci } 6448c2ecf20Sopenharmony_ci 6458c2ecf20Sopenharmony_ci return 0; 6468c2ecf20Sopenharmony_ci} 6478c2ecf20Sopenharmony_ci 6488c2ecf20Sopenharmony_ci/** 6498c2ecf20Sopenharmony_ci * bdisp_hw_get_op_cfg 6508c2ecf20Sopenharmony_ci * @ctx: device context 6518c2ecf20Sopenharmony_ci * @c: operation configuration 6528c2ecf20Sopenharmony_ci * 6538c2ecf20Sopenharmony_ci * Check which blitter operations are expected and sets the scaling increments 6548c2ecf20Sopenharmony_ci * 6558c2ecf20Sopenharmony_ci * RETURNS: 6568c2ecf20Sopenharmony_ci * 0 on success 6578c2ecf20Sopenharmony_ci */ 6588c2ecf20Sopenharmony_cistatic int bdisp_hw_get_op_cfg(struct bdisp_ctx *ctx, struct bdisp_op_cfg *c) 6598c2ecf20Sopenharmony_ci{ 6608c2ecf20Sopenharmony_ci struct device *dev = ctx->bdisp_dev->dev; 6618c2ecf20Sopenharmony_ci struct bdisp_frame *src = &ctx->src; 6628c2ecf20Sopenharmony_ci struct bdisp_frame *dst = &ctx->dst; 6638c2ecf20Sopenharmony_ci 6648c2ecf20Sopenharmony_ci if (src->width > MAX_SRC_WIDTH * MAX_VERTICAL_STRIDES) { 6658c2ecf20Sopenharmony_ci dev_err(dev, "Image width out of HW caps\n"); 6668c2ecf20Sopenharmony_ci return -EINVAL; 6678c2ecf20Sopenharmony_ci } 6688c2ecf20Sopenharmony_ci 6698c2ecf20Sopenharmony_ci c->wide = src->width > MAX_SRC_WIDTH; 6708c2ecf20Sopenharmony_ci 6718c2ecf20Sopenharmony_ci c->hflip = ctx->hflip; 6728c2ecf20Sopenharmony_ci c->vflip = ctx->vflip; 6738c2ecf20Sopenharmony_ci 6748c2ecf20Sopenharmony_ci c->src_interlaced = (src->field == V4L2_FIELD_INTERLACED); 6758c2ecf20Sopenharmony_ci 6768c2ecf20Sopenharmony_ci c->src_nbp = src->fmt->nb_planes; 6778c2ecf20Sopenharmony_ci c->src_yuv = (src->fmt->pixelformat == V4L2_PIX_FMT_NV12) || 6788c2ecf20Sopenharmony_ci (src->fmt->pixelformat == V4L2_PIX_FMT_YUV420); 6798c2ecf20Sopenharmony_ci c->src_420 = c->src_yuv; 6808c2ecf20Sopenharmony_ci 6818c2ecf20Sopenharmony_ci c->dst_nbp = dst->fmt->nb_planes; 6828c2ecf20Sopenharmony_ci c->dst_yuv = (dst->fmt->pixelformat == V4L2_PIX_FMT_NV12) || 6838c2ecf20Sopenharmony_ci (dst->fmt->pixelformat == V4L2_PIX_FMT_YUV420); 6848c2ecf20Sopenharmony_ci c->dst_420 = c->dst_yuv; 6858c2ecf20Sopenharmony_ci 6868c2ecf20Sopenharmony_ci c->cconv = (c->src_yuv != c->dst_yuv); 6878c2ecf20Sopenharmony_ci 6888c2ecf20Sopenharmony_ci if (bdisp_hw_get_hv_inc(ctx, &c->h_inc, &c->v_inc)) { 6898c2ecf20Sopenharmony_ci dev_err(dev, "Scale factor out of HW caps\n"); 6908c2ecf20Sopenharmony_ci return -EINVAL; 6918c2ecf20Sopenharmony_ci } 6928c2ecf20Sopenharmony_ci 6938c2ecf20Sopenharmony_ci /* Deinterlacing adjustment : stretch a field to a frame */ 6948c2ecf20Sopenharmony_ci if (c->src_interlaced) 6958c2ecf20Sopenharmony_ci c->v_inc /= 2; 6968c2ecf20Sopenharmony_ci 6978c2ecf20Sopenharmony_ci if ((c->h_inc != (1 << 10)) || (c->v_inc != (1 << 10))) 6988c2ecf20Sopenharmony_ci c->scale = true; 6998c2ecf20Sopenharmony_ci else 7008c2ecf20Sopenharmony_ci c->scale = false; 7018c2ecf20Sopenharmony_ci 7028c2ecf20Sopenharmony_ci return 0; 7038c2ecf20Sopenharmony_ci} 7048c2ecf20Sopenharmony_ci 7058c2ecf20Sopenharmony_ci/** 7068c2ecf20Sopenharmony_ci * bdisp_hw_color_format 7078c2ecf20Sopenharmony_ci * @pixelformat: v4l2 pixel format 7088c2ecf20Sopenharmony_ci * 7098c2ecf20Sopenharmony_ci * v4l2 to bdisp pixel format convert 7108c2ecf20Sopenharmony_ci * 7118c2ecf20Sopenharmony_ci * RETURNS: 7128c2ecf20Sopenharmony_ci * bdisp pixel format 7138c2ecf20Sopenharmony_ci */ 7148c2ecf20Sopenharmony_cistatic u32 bdisp_hw_color_format(u32 pixelformat) 7158c2ecf20Sopenharmony_ci{ 7168c2ecf20Sopenharmony_ci u32 ret; 7178c2ecf20Sopenharmony_ci 7188c2ecf20Sopenharmony_ci switch (pixelformat) { 7198c2ecf20Sopenharmony_ci case V4L2_PIX_FMT_YUV420: 7208c2ecf20Sopenharmony_ci ret = (BDISP_YUV_3B << BLT_TTY_COL_SHIFT); 7218c2ecf20Sopenharmony_ci break; 7228c2ecf20Sopenharmony_ci case V4L2_PIX_FMT_NV12: 7238c2ecf20Sopenharmony_ci ret = (BDISP_NV12 << BLT_TTY_COL_SHIFT) | BLT_TTY_BIG_END; 7248c2ecf20Sopenharmony_ci break; 7258c2ecf20Sopenharmony_ci case V4L2_PIX_FMT_RGB565: 7268c2ecf20Sopenharmony_ci ret = (BDISP_RGB565 << BLT_TTY_COL_SHIFT); 7278c2ecf20Sopenharmony_ci break; 7288c2ecf20Sopenharmony_ci case V4L2_PIX_FMT_XBGR32: /* This V4L format actually refers to xRGB */ 7298c2ecf20Sopenharmony_ci ret = (BDISP_XRGB8888 << BLT_TTY_COL_SHIFT); 7308c2ecf20Sopenharmony_ci break; 7318c2ecf20Sopenharmony_ci case V4L2_PIX_FMT_RGB24: /* RGB888 format */ 7328c2ecf20Sopenharmony_ci ret = (BDISP_RGB888 << BLT_TTY_COL_SHIFT) | BLT_TTY_BIG_END; 7338c2ecf20Sopenharmony_ci break; 7348c2ecf20Sopenharmony_ci case V4L2_PIX_FMT_ABGR32: /* This V4L format actually refers to ARGB */ 7358c2ecf20Sopenharmony_ci 7368c2ecf20Sopenharmony_ci default: 7378c2ecf20Sopenharmony_ci ret = (BDISP_ARGB8888 << BLT_TTY_COL_SHIFT) | BLT_TTY_ALPHA_R; 7388c2ecf20Sopenharmony_ci break; 7398c2ecf20Sopenharmony_ci } 7408c2ecf20Sopenharmony_ci 7418c2ecf20Sopenharmony_ci return ret; 7428c2ecf20Sopenharmony_ci} 7438c2ecf20Sopenharmony_ci 7448c2ecf20Sopenharmony_ci/** 7458c2ecf20Sopenharmony_ci * bdisp_hw_build_node 7468c2ecf20Sopenharmony_ci * @ctx: device context 7478c2ecf20Sopenharmony_ci * @cfg: operation configuration 7488c2ecf20Sopenharmony_ci * @node: node to be set 7498c2ecf20Sopenharmony_ci * @t_plan: whether the node refers to a RGB/Y or a CbCr plane 7508c2ecf20Sopenharmony_ci * @src_x_offset: x offset in the source image 7518c2ecf20Sopenharmony_ci * 7528c2ecf20Sopenharmony_ci * Build a node 7538c2ecf20Sopenharmony_ci * 7548c2ecf20Sopenharmony_ci * RETURNS: 7558c2ecf20Sopenharmony_ci * None 7568c2ecf20Sopenharmony_ci */ 7578c2ecf20Sopenharmony_cistatic void bdisp_hw_build_node(struct bdisp_ctx *ctx, 7588c2ecf20Sopenharmony_ci struct bdisp_op_cfg *cfg, 7598c2ecf20Sopenharmony_ci struct bdisp_node *node, 7608c2ecf20Sopenharmony_ci enum bdisp_target_plan t_plan, int src_x_offset) 7618c2ecf20Sopenharmony_ci{ 7628c2ecf20Sopenharmony_ci struct bdisp_frame *src = &ctx->src; 7638c2ecf20Sopenharmony_ci struct bdisp_frame *dst = &ctx->dst; 7648c2ecf20Sopenharmony_ci u16 h_inc, v_inc, yh_inc, yv_inc; 7658c2ecf20Sopenharmony_ci struct v4l2_rect src_rect = src->crop; 7668c2ecf20Sopenharmony_ci struct v4l2_rect dst_rect = dst->crop; 7678c2ecf20Sopenharmony_ci int dst_x_offset; 7688c2ecf20Sopenharmony_ci s32 dst_width = dst->crop.width; 7698c2ecf20Sopenharmony_ci u32 src_fmt, dst_fmt; 7708c2ecf20Sopenharmony_ci const u32 *ivmx; 7718c2ecf20Sopenharmony_ci 7728c2ecf20Sopenharmony_ci dev_dbg(ctx->bdisp_dev->dev, "%s\n", __func__); 7738c2ecf20Sopenharmony_ci 7748c2ecf20Sopenharmony_ci memset(node, 0, sizeof(*node)); 7758c2ecf20Sopenharmony_ci 7768c2ecf20Sopenharmony_ci /* Adjust src and dst areas wrt src_x_offset */ 7778c2ecf20Sopenharmony_ci src_rect.left += src_x_offset; 7788c2ecf20Sopenharmony_ci src_rect.width -= src_x_offset; 7798c2ecf20Sopenharmony_ci src_rect.width = min_t(__s32, MAX_SRC_WIDTH, src_rect.width); 7808c2ecf20Sopenharmony_ci 7818c2ecf20Sopenharmony_ci dst_x_offset = (src_x_offset * dst_width) / ctx->src.crop.width; 7828c2ecf20Sopenharmony_ci dst_rect.left += dst_x_offset; 7838c2ecf20Sopenharmony_ci dst_rect.width = (src_rect.width * dst_width) / ctx->src.crop.width; 7848c2ecf20Sopenharmony_ci 7858c2ecf20Sopenharmony_ci /* General */ 7868c2ecf20Sopenharmony_ci src_fmt = src->fmt->pixelformat; 7878c2ecf20Sopenharmony_ci dst_fmt = dst->fmt->pixelformat; 7888c2ecf20Sopenharmony_ci 7898c2ecf20Sopenharmony_ci node->nip = 0; 7908c2ecf20Sopenharmony_ci node->cic = BLT_CIC_ALL_GRP; 7918c2ecf20Sopenharmony_ci node->ack = BLT_ACK_BYPASS_S2S3; 7928c2ecf20Sopenharmony_ci 7938c2ecf20Sopenharmony_ci switch (cfg->src_nbp) { 7948c2ecf20Sopenharmony_ci case 1: 7958c2ecf20Sopenharmony_ci /* Src2 = RGB / Src1 = Src3 = off */ 7968c2ecf20Sopenharmony_ci node->ins = BLT_INS_S1_OFF | BLT_INS_S2_MEM | BLT_INS_S3_OFF; 7978c2ecf20Sopenharmony_ci break; 7988c2ecf20Sopenharmony_ci case 2: 7998c2ecf20Sopenharmony_ci /* Src3 = Y 8008c2ecf20Sopenharmony_ci * Src2 = CbCr or ColorFill if writing the Y plane 8018c2ecf20Sopenharmony_ci * Src1 = off */ 8028c2ecf20Sopenharmony_ci node->ins = BLT_INS_S1_OFF | BLT_INS_S3_MEM; 8038c2ecf20Sopenharmony_ci if (t_plan == BDISP_Y) 8048c2ecf20Sopenharmony_ci node->ins |= BLT_INS_S2_CF; 8058c2ecf20Sopenharmony_ci else 8068c2ecf20Sopenharmony_ci node->ins |= BLT_INS_S2_MEM; 8078c2ecf20Sopenharmony_ci break; 8088c2ecf20Sopenharmony_ci case 3: 8098c2ecf20Sopenharmony_ci default: 8108c2ecf20Sopenharmony_ci /* Src3 = Y 8118c2ecf20Sopenharmony_ci * Src2 = Cb or ColorFill if writing the Y plane 8128c2ecf20Sopenharmony_ci * Src1 = Cr or ColorFill if writing the Y plane */ 8138c2ecf20Sopenharmony_ci node->ins = BLT_INS_S3_MEM; 8148c2ecf20Sopenharmony_ci if (t_plan == BDISP_Y) 8158c2ecf20Sopenharmony_ci node->ins |= BLT_INS_S2_CF | BLT_INS_S1_CF; 8168c2ecf20Sopenharmony_ci else 8178c2ecf20Sopenharmony_ci node->ins |= BLT_INS_S2_MEM | BLT_INS_S1_MEM; 8188c2ecf20Sopenharmony_ci break; 8198c2ecf20Sopenharmony_ci } 8208c2ecf20Sopenharmony_ci 8218c2ecf20Sopenharmony_ci /* Color convert */ 8228c2ecf20Sopenharmony_ci node->ins |= cfg->cconv ? BLT_INS_IVMX : 0; 8238c2ecf20Sopenharmony_ci /* Scale needed if scaling OR 4:2:0 up/downsampling */ 8248c2ecf20Sopenharmony_ci node->ins |= (cfg->scale || cfg->src_420 || cfg->dst_420) ? 8258c2ecf20Sopenharmony_ci BLT_INS_SCALE : 0; 8268c2ecf20Sopenharmony_ci 8278c2ecf20Sopenharmony_ci /* Target */ 8288c2ecf20Sopenharmony_ci node->tba = (t_plan == BDISP_CBCR) ? dst->paddr[1] : dst->paddr[0]; 8298c2ecf20Sopenharmony_ci 8308c2ecf20Sopenharmony_ci node->tty = dst->bytesperline; 8318c2ecf20Sopenharmony_ci node->tty |= bdisp_hw_color_format(dst_fmt); 8328c2ecf20Sopenharmony_ci node->tty |= BLT_TTY_DITHER; 8338c2ecf20Sopenharmony_ci node->tty |= (t_plan == BDISP_CBCR) ? BLT_TTY_CHROMA : 0; 8348c2ecf20Sopenharmony_ci node->tty |= cfg->hflip ? BLT_TTY_HSO : 0; 8358c2ecf20Sopenharmony_ci node->tty |= cfg->vflip ? BLT_TTY_VSO : 0; 8368c2ecf20Sopenharmony_ci 8378c2ecf20Sopenharmony_ci if (cfg->dst_420 && (t_plan == BDISP_CBCR)) { 8388c2ecf20Sopenharmony_ci /* 420 chroma downsampling */ 8398c2ecf20Sopenharmony_ci dst_rect.height /= 2; 8408c2ecf20Sopenharmony_ci dst_rect.width /= 2; 8418c2ecf20Sopenharmony_ci dst_rect.left /= 2; 8428c2ecf20Sopenharmony_ci dst_rect.top /= 2; 8438c2ecf20Sopenharmony_ci dst_x_offset /= 2; 8448c2ecf20Sopenharmony_ci dst_width /= 2; 8458c2ecf20Sopenharmony_ci } 8468c2ecf20Sopenharmony_ci 8478c2ecf20Sopenharmony_ci node->txy = cfg->vflip ? (dst_rect.height - 1) : dst_rect.top; 8488c2ecf20Sopenharmony_ci node->txy <<= 16; 8498c2ecf20Sopenharmony_ci node->txy |= cfg->hflip ? (dst_width - dst_x_offset - 1) : 8508c2ecf20Sopenharmony_ci dst_rect.left; 8518c2ecf20Sopenharmony_ci 8528c2ecf20Sopenharmony_ci node->tsz = dst_rect.height << 16 | dst_rect.width; 8538c2ecf20Sopenharmony_ci 8548c2ecf20Sopenharmony_ci if (cfg->src_interlaced) { 8558c2ecf20Sopenharmony_ci /* handle only the top field which is half height of a frame */ 8568c2ecf20Sopenharmony_ci src_rect.top /= 2; 8578c2ecf20Sopenharmony_ci src_rect.height /= 2; 8588c2ecf20Sopenharmony_ci } 8598c2ecf20Sopenharmony_ci 8608c2ecf20Sopenharmony_ci if (cfg->src_nbp == 1) { 8618c2ecf20Sopenharmony_ci /* Src 2 : RGB */ 8628c2ecf20Sopenharmony_ci node->s2ba = src->paddr[0]; 8638c2ecf20Sopenharmony_ci 8648c2ecf20Sopenharmony_ci node->s2ty = src->bytesperline; 8658c2ecf20Sopenharmony_ci if (cfg->src_interlaced) 8668c2ecf20Sopenharmony_ci node->s2ty *= 2; 8678c2ecf20Sopenharmony_ci 8688c2ecf20Sopenharmony_ci node->s2ty |= bdisp_hw_color_format(src_fmt); 8698c2ecf20Sopenharmony_ci 8708c2ecf20Sopenharmony_ci node->s2xy = src_rect.top << 16 | src_rect.left; 8718c2ecf20Sopenharmony_ci node->s2sz = src_rect.height << 16 | src_rect.width; 8728c2ecf20Sopenharmony_ci } else { 8738c2ecf20Sopenharmony_ci /* Src 2 : Cb or CbCr */ 8748c2ecf20Sopenharmony_ci if (cfg->src_420) { 8758c2ecf20Sopenharmony_ci /* 420 chroma upsampling */ 8768c2ecf20Sopenharmony_ci src_rect.top /= 2; 8778c2ecf20Sopenharmony_ci src_rect.left /= 2; 8788c2ecf20Sopenharmony_ci src_rect.width /= 2; 8798c2ecf20Sopenharmony_ci src_rect.height /= 2; 8808c2ecf20Sopenharmony_ci } 8818c2ecf20Sopenharmony_ci 8828c2ecf20Sopenharmony_ci node->s2ba = src->paddr[1]; 8838c2ecf20Sopenharmony_ci 8848c2ecf20Sopenharmony_ci node->s2ty = src->bytesperline; 8858c2ecf20Sopenharmony_ci if (cfg->src_nbp == 3) 8868c2ecf20Sopenharmony_ci node->s2ty /= 2; 8878c2ecf20Sopenharmony_ci if (cfg->src_interlaced) 8888c2ecf20Sopenharmony_ci node->s2ty *= 2; 8898c2ecf20Sopenharmony_ci 8908c2ecf20Sopenharmony_ci node->s2ty |= bdisp_hw_color_format(src_fmt); 8918c2ecf20Sopenharmony_ci 8928c2ecf20Sopenharmony_ci node->s2xy = src_rect.top << 16 | src_rect.left; 8938c2ecf20Sopenharmony_ci node->s2sz = src_rect.height << 16 | src_rect.width; 8948c2ecf20Sopenharmony_ci 8958c2ecf20Sopenharmony_ci if (cfg->src_nbp == 3) { 8968c2ecf20Sopenharmony_ci /* Src 1 : Cr */ 8978c2ecf20Sopenharmony_ci node->s1ba = src->paddr[2]; 8988c2ecf20Sopenharmony_ci 8998c2ecf20Sopenharmony_ci node->s1ty = node->s2ty; 9008c2ecf20Sopenharmony_ci node->s1xy = node->s2xy; 9018c2ecf20Sopenharmony_ci } 9028c2ecf20Sopenharmony_ci 9038c2ecf20Sopenharmony_ci /* Src 3 : Y */ 9048c2ecf20Sopenharmony_ci node->s3ba = src->paddr[0]; 9058c2ecf20Sopenharmony_ci 9068c2ecf20Sopenharmony_ci node->s3ty = src->bytesperline; 9078c2ecf20Sopenharmony_ci if (cfg->src_interlaced) 9088c2ecf20Sopenharmony_ci node->s3ty *= 2; 9098c2ecf20Sopenharmony_ci node->s3ty |= bdisp_hw_color_format(src_fmt); 9108c2ecf20Sopenharmony_ci 9118c2ecf20Sopenharmony_ci if ((t_plan != BDISP_CBCR) && cfg->src_420) { 9128c2ecf20Sopenharmony_ci /* No chroma upsampling for output RGB / Y plane */ 9138c2ecf20Sopenharmony_ci node->s3xy = node->s2xy * 2; 9148c2ecf20Sopenharmony_ci node->s3sz = node->s2sz * 2; 9158c2ecf20Sopenharmony_ci } else { 9168c2ecf20Sopenharmony_ci /* No need to read Y (Src3) when writing Chroma */ 9178c2ecf20Sopenharmony_ci node->s3ty |= BLT_S3TY_BLANK_ACC; 9188c2ecf20Sopenharmony_ci node->s3xy = node->s2xy; 9198c2ecf20Sopenharmony_ci node->s3sz = node->s2sz; 9208c2ecf20Sopenharmony_ci } 9218c2ecf20Sopenharmony_ci } 9228c2ecf20Sopenharmony_ci 9238c2ecf20Sopenharmony_ci /* Resize (scale OR 4:2:0: chroma up/downsampling) */ 9248c2ecf20Sopenharmony_ci if (node->ins & BLT_INS_SCALE) { 9258c2ecf20Sopenharmony_ci /* no need to compute Y when writing CbCr from RGB input */ 9268c2ecf20Sopenharmony_ci bool skip_y = (t_plan == BDISP_CBCR) && !cfg->src_yuv; 9278c2ecf20Sopenharmony_ci 9288c2ecf20Sopenharmony_ci /* FCTL */ 9298c2ecf20Sopenharmony_ci if (cfg->scale) { 9308c2ecf20Sopenharmony_ci node->fctl = BLT_FCTL_HV_SCALE; 9318c2ecf20Sopenharmony_ci if (!skip_y) 9328c2ecf20Sopenharmony_ci node->fctl |= BLT_FCTL_Y_HV_SCALE; 9338c2ecf20Sopenharmony_ci } else { 9348c2ecf20Sopenharmony_ci node->fctl = BLT_FCTL_HV_SAMPLE; 9358c2ecf20Sopenharmony_ci if (!skip_y) 9368c2ecf20Sopenharmony_ci node->fctl |= BLT_FCTL_Y_HV_SAMPLE; 9378c2ecf20Sopenharmony_ci } 9388c2ecf20Sopenharmony_ci 9398c2ecf20Sopenharmony_ci /* RSF - Chroma may need to be up/downsampled */ 9408c2ecf20Sopenharmony_ci h_inc = cfg->h_inc; 9418c2ecf20Sopenharmony_ci v_inc = cfg->v_inc; 9428c2ecf20Sopenharmony_ci if (!cfg->src_420 && cfg->dst_420 && (t_plan == BDISP_CBCR)) { 9438c2ecf20Sopenharmony_ci /* RGB to 4:2:0 for Chroma: downsample */ 9448c2ecf20Sopenharmony_ci h_inc *= 2; 9458c2ecf20Sopenharmony_ci v_inc *= 2; 9468c2ecf20Sopenharmony_ci } else if (cfg->src_420 && !cfg->dst_420) { 9478c2ecf20Sopenharmony_ci /* 4:2:0: to RGB: upsample*/ 9488c2ecf20Sopenharmony_ci h_inc /= 2; 9498c2ecf20Sopenharmony_ci v_inc /= 2; 9508c2ecf20Sopenharmony_ci } 9518c2ecf20Sopenharmony_ci node->rsf = v_inc << 16 | h_inc; 9528c2ecf20Sopenharmony_ci 9538c2ecf20Sopenharmony_ci /* RZI */ 9548c2ecf20Sopenharmony_ci node->rzi = BLT_RZI_DEFAULT; 9558c2ecf20Sopenharmony_ci 9568c2ecf20Sopenharmony_ci /* Filter table physical addr */ 9578c2ecf20Sopenharmony_ci node->hfp = bdisp_hw_get_hf_addr(h_inc); 9588c2ecf20Sopenharmony_ci node->vfp = bdisp_hw_get_vf_addr(v_inc); 9598c2ecf20Sopenharmony_ci 9608c2ecf20Sopenharmony_ci /* Y version */ 9618c2ecf20Sopenharmony_ci if (!skip_y) { 9628c2ecf20Sopenharmony_ci yh_inc = cfg->h_inc; 9638c2ecf20Sopenharmony_ci yv_inc = cfg->v_inc; 9648c2ecf20Sopenharmony_ci 9658c2ecf20Sopenharmony_ci node->y_rsf = yv_inc << 16 | yh_inc; 9668c2ecf20Sopenharmony_ci node->y_rzi = BLT_RZI_DEFAULT; 9678c2ecf20Sopenharmony_ci node->y_hfp = bdisp_hw_get_hf_addr(yh_inc); 9688c2ecf20Sopenharmony_ci node->y_vfp = bdisp_hw_get_vf_addr(yv_inc); 9698c2ecf20Sopenharmony_ci } 9708c2ecf20Sopenharmony_ci } 9718c2ecf20Sopenharmony_ci 9728c2ecf20Sopenharmony_ci /* Versatile matrix for RGB / YUV conversion */ 9738c2ecf20Sopenharmony_ci if (cfg->cconv) { 9748c2ecf20Sopenharmony_ci ivmx = cfg->src_yuv ? bdisp_yuv_to_rgb : bdisp_rgb_to_yuv; 9758c2ecf20Sopenharmony_ci 9768c2ecf20Sopenharmony_ci node->ivmx0 = ivmx[0]; 9778c2ecf20Sopenharmony_ci node->ivmx1 = ivmx[1]; 9788c2ecf20Sopenharmony_ci node->ivmx2 = ivmx[2]; 9798c2ecf20Sopenharmony_ci node->ivmx3 = ivmx[3]; 9808c2ecf20Sopenharmony_ci } 9818c2ecf20Sopenharmony_ci} 9828c2ecf20Sopenharmony_ci 9838c2ecf20Sopenharmony_ci/** 9848c2ecf20Sopenharmony_ci * bdisp_hw_build_all_nodes 9858c2ecf20Sopenharmony_ci * @ctx: device context 9868c2ecf20Sopenharmony_ci * 9878c2ecf20Sopenharmony_ci * Build all the nodes for the blitter operation 9888c2ecf20Sopenharmony_ci * 9898c2ecf20Sopenharmony_ci * RETURNS: 9908c2ecf20Sopenharmony_ci * 0 on success 9918c2ecf20Sopenharmony_ci */ 9928c2ecf20Sopenharmony_cistatic int bdisp_hw_build_all_nodes(struct bdisp_ctx *ctx) 9938c2ecf20Sopenharmony_ci{ 9948c2ecf20Sopenharmony_ci struct bdisp_op_cfg cfg; 9958c2ecf20Sopenharmony_ci unsigned int i, nid = 0; 9968c2ecf20Sopenharmony_ci int src_x_offset = 0; 9978c2ecf20Sopenharmony_ci 9988c2ecf20Sopenharmony_ci for (i = 0; i < MAX_NB_NODE; i++) 9998c2ecf20Sopenharmony_ci if (!ctx->node[i]) { 10008c2ecf20Sopenharmony_ci dev_err(ctx->bdisp_dev->dev, "node %d is null\n", i); 10018c2ecf20Sopenharmony_ci return -EINVAL; 10028c2ecf20Sopenharmony_ci } 10038c2ecf20Sopenharmony_ci 10048c2ecf20Sopenharmony_ci /* Get configuration (scale, flip, ...) */ 10058c2ecf20Sopenharmony_ci if (bdisp_hw_get_op_cfg(ctx, &cfg)) 10068c2ecf20Sopenharmony_ci return -EINVAL; 10078c2ecf20Sopenharmony_ci 10088c2ecf20Sopenharmony_ci /* Split source in vertical strides (HW constraint) */ 10098c2ecf20Sopenharmony_ci for (i = 0; i < MAX_VERTICAL_STRIDES; i++) { 10108c2ecf20Sopenharmony_ci /* Build RGB/Y node and link it to the previous node */ 10118c2ecf20Sopenharmony_ci bdisp_hw_build_node(ctx, &cfg, ctx->node[nid], 10128c2ecf20Sopenharmony_ci cfg.dst_nbp == 1 ? BDISP_RGB : BDISP_Y, 10138c2ecf20Sopenharmony_ci src_x_offset); 10148c2ecf20Sopenharmony_ci if (nid) 10158c2ecf20Sopenharmony_ci ctx->node[nid - 1]->nip = ctx->node_paddr[nid]; 10168c2ecf20Sopenharmony_ci nid++; 10178c2ecf20Sopenharmony_ci 10188c2ecf20Sopenharmony_ci /* Build additional Cb(Cr) node, link it to the previous one */ 10198c2ecf20Sopenharmony_ci if (cfg.dst_nbp > 1) { 10208c2ecf20Sopenharmony_ci bdisp_hw_build_node(ctx, &cfg, ctx->node[nid], 10218c2ecf20Sopenharmony_ci BDISP_CBCR, src_x_offset); 10228c2ecf20Sopenharmony_ci ctx->node[nid - 1]->nip = ctx->node_paddr[nid]; 10238c2ecf20Sopenharmony_ci nid++; 10248c2ecf20Sopenharmony_ci } 10258c2ecf20Sopenharmony_ci 10268c2ecf20Sopenharmony_ci /* Next stride until full width covered */ 10278c2ecf20Sopenharmony_ci src_x_offset += MAX_SRC_WIDTH; 10288c2ecf20Sopenharmony_ci if (src_x_offset >= ctx->src.crop.width) 10298c2ecf20Sopenharmony_ci break; 10308c2ecf20Sopenharmony_ci } 10318c2ecf20Sopenharmony_ci 10328c2ecf20Sopenharmony_ci /* Mark last node as the last */ 10338c2ecf20Sopenharmony_ci ctx->node[nid - 1]->nip = 0; 10348c2ecf20Sopenharmony_ci 10358c2ecf20Sopenharmony_ci return 0; 10368c2ecf20Sopenharmony_ci} 10378c2ecf20Sopenharmony_ci 10388c2ecf20Sopenharmony_ci/** 10398c2ecf20Sopenharmony_ci * bdisp_hw_save_request 10408c2ecf20Sopenharmony_ci * @ctx: device context 10418c2ecf20Sopenharmony_ci * 10428c2ecf20Sopenharmony_ci * Save a copy of the request and of the built nodes 10438c2ecf20Sopenharmony_ci * 10448c2ecf20Sopenharmony_ci * RETURNS: 10458c2ecf20Sopenharmony_ci * None 10468c2ecf20Sopenharmony_ci */ 10478c2ecf20Sopenharmony_cistatic void bdisp_hw_save_request(struct bdisp_ctx *ctx) 10488c2ecf20Sopenharmony_ci{ 10498c2ecf20Sopenharmony_ci struct bdisp_node **copy_node = ctx->bdisp_dev->dbg.copy_node; 10508c2ecf20Sopenharmony_ci struct bdisp_request *request = &ctx->bdisp_dev->dbg.copy_request; 10518c2ecf20Sopenharmony_ci struct bdisp_node **node = ctx->node; 10528c2ecf20Sopenharmony_ci int i; 10538c2ecf20Sopenharmony_ci 10548c2ecf20Sopenharmony_ci /* Request copy */ 10558c2ecf20Sopenharmony_ci request->src = ctx->src; 10568c2ecf20Sopenharmony_ci request->dst = ctx->dst; 10578c2ecf20Sopenharmony_ci request->hflip = ctx->hflip; 10588c2ecf20Sopenharmony_ci request->vflip = ctx->vflip; 10598c2ecf20Sopenharmony_ci request->nb_req++; 10608c2ecf20Sopenharmony_ci 10618c2ecf20Sopenharmony_ci /* Nodes copy */ 10628c2ecf20Sopenharmony_ci for (i = 0; i < MAX_NB_NODE; i++) { 10638c2ecf20Sopenharmony_ci /* Allocate memory if not done yet */ 10648c2ecf20Sopenharmony_ci if (!copy_node[i]) { 10658c2ecf20Sopenharmony_ci copy_node[i] = devm_kzalloc(ctx->bdisp_dev->dev, 10668c2ecf20Sopenharmony_ci sizeof(*copy_node[i]), 10678c2ecf20Sopenharmony_ci GFP_ATOMIC); 10688c2ecf20Sopenharmony_ci if (!copy_node[i]) 10698c2ecf20Sopenharmony_ci return; 10708c2ecf20Sopenharmony_ci } 10718c2ecf20Sopenharmony_ci *copy_node[i] = *node[i]; 10728c2ecf20Sopenharmony_ci } 10738c2ecf20Sopenharmony_ci} 10748c2ecf20Sopenharmony_ci 10758c2ecf20Sopenharmony_ci/** 10768c2ecf20Sopenharmony_ci * bdisp_hw_update 10778c2ecf20Sopenharmony_ci * @ctx: device context 10788c2ecf20Sopenharmony_ci * 10798c2ecf20Sopenharmony_ci * Send the request to the HW 10808c2ecf20Sopenharmony_ci * 10818c2ecf20Sopenharmony_ci * RETURNS: 10828c2ecf20Sopenharmony_ci * 0 on success 10838c2ecf20Sopenharmony_ci */ 10848c2ecf20Sopenharmony_ciint bdisp_hw_update(struct bdisp_ctx *ctx) 10858c2ecf20Sopenharmony_ci{ 10868c2ecf20Sopenharmony_ci int ret; 10878c2ecf20Sopenharmony_ci struct bdisp_dev *bdisp = ctx->bdisp_dev; 10888c2ecf20Sopenharmony_ci struct device *dev = bdisp->dev; 10898c2ecf20Sopenharmony_ci unsigned int node_id; 10908c2ecf20Sopenharmony_ci 10918c2ecf20Sopenharmony_ci dev_dbg(dev, "%s\n", __func__); 10928c2ecf20Sopenharmony_ci 10938c2ecf20Sopenharmony_ci /* build nodes */ 10948c2ecf20Sopenharmony_ci ret = bdisp_hw_build_all_nodes(ctx); 10958c2ecf20Sopenharmony_ci if (ret) { 10968c2ecf20Sopenharmony_ci dev_err(dev, "cannot build nodes (%d)\n", ret); 10978c2ecf20Sopenharmony_ci return ret; 10988c2ecf20Sopenharmony_ci } 10998c2ecf20Sopenharmony_ci 11008c2ecf20Sopenharmony_ci /* Save a copy of the request */ 11018c2ecf20Sopenharmony_ci bdisp_hw_save_request(ctx); 11028c2ecf20Sopenharmony_ci 11038c2ecf20Sopenharmony_ci /* Configure interrupt to 'Last Node Reached for AQ1' */ 11048c2ecf20Sopenharmony_ci writel(BLT_AQ1_CTL_CFG, bdisp->regs + BLT_AQ1_CTL); 11058c2ecf20Sopenharmony_ci writel(BLT_ITS_AQ1_LNA, bdisp->regs + BLT_ITM0); 11068c2ecf20Sopenharmony_ci 11078c2ecf20Sopenharmony_ci /* Write first node addr */ 11088c2ecf20Sopenharmony_ci writel(ctx->node_paddr[0], bdisp->regs + BLT_AQ1_IP); 11098c2ecf20Sopenharmony_ci 11108c2ecf20Sopenharmony_ci /* Find and write last node addr : this starts the HW processing */ 11118c2ecf20Sopenharmony_ci for (node_id = 0; node_id < MAX_NB_NODE - 1; node_id++) { 11128c2ecf20Sopenharmony_ci if (!ctx->node[node_id]->nip) 11138c2ecf20Sopenharmony_ci break; 11148c2ecf20Sopenharmony_ci } 11158c2ecf20Sopenharmony_ci writel(ctx->node_paddr[node_id], bdisp->regs + BLT_AQ1_LNA); 11168c2ecf20Sopenharmony_ci 11178c2ecf20Sopenharmony_ci return 0; 11188c2ecf20Sopenharmony_ci} 1119