18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright © 2007 Dave Mueller 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 58c2ecf20Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 68c2ecf20Sopenharmony_ci * to deal in the Software without restriction, including without limitation 78c2ecf20Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 88c2ecf20Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 98c2ecf20Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * The above copyright notice and this permission notice (including the next 128c2ecf20Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 138c2ecf20Sopenharmony_ci * Software. 148c2ecf20Sopenharmony_ci * 158c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 168c2ecf20Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 178c2ecf20Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 188c2ecf20Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 198c2ecf20Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 208c2ecf20Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 218c2ecf20Sopenharmony_ci * IN THE SOFTWARE. 228c2ecf20Sopenharmony_ci * 238c2ecf20Sopenharmony_ci * Authors: 248c2ecf20Sopenharmony_ci * Dave Mueller <dave.mueller@gmx.ch> 258c2ecf20Sopenharmony_ci * 268c2ecf20Sopenharmony_ci */ 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci#include "intel_display_types.h" 298c2ecf20Sopenharmony_ci#include "intel_dvo_dev.h" 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci/* register definitions according to the TFP410 data sheet */ 328c2ecf20Sopenharmony_ci#define TFP410_VID 0x014C 338c2ecf20Sopenharmony_ci#define TFP410_DID 0x0410 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci#define TFP410_VID_LO 0x00 368c2ecf20Sopenharmony_ci#define TFP410_VID_HI 0x01 378c2ecf20Sopenharmony_ci#define TFP410_DID_LO 0x02 388c2ecf20Sopenharmony_ci#define TFP410_DID_HI 0x03 398c2ecf20Sopenharmony_ci#define TFP410_REV 0x04 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci#define TFP410_CTL_1 0x08 428c2ecf20Sopenharmony_ci#define TFP410_CTL_1_TDIS (1<<6) 438c2ecf20Sopenharmony_ci#define TFP410_CTL_1_VEN (1<<5) 448c2ecf20Sopenharmony_ci#define TFP410_CTL_1_HEN (1<<4) 458c2ecf20Sopenharmony_ci#define TFP410_CTL_1_DSEL (1<<3) 468c2ecf20Sopenharmony_ci#define TFP410_CTL_1_BSEL (1<<2) 478c2ecf20Sopenharmony_ci#define TFP410_CTL_1_EDGE (1<<1) 488c2ecf20Sopenharmony_ci#define TFP410_CTL_1_PD (1<<0) 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci#define TFP410_CTL_2 0x09 518c2ecf20Sopenharmony_ci#define TFP410_CTL_2_VLOW (1<<7) 528c2ecf20Sopenharmony_ci#define TFP410_CTL_2_MSEL_MASK (0x7<<4) 538c2ecf20Sopenharmony_ci#define TFP410_CTL_2_MSEL (1<<4) 548c2ecf20Sopenharmony_ci#define TFP410_CTL_2_TSEL (1<<3) 558c2ecf20Sopenharmony_ci#define TFP410_CTL_2_RSEN (1<<2) 568c2ecf20Sopenharmony_ci#define TFP410_CTL_2_HTPLG (1<<1) 578c2ecf20Sopenharmony_ci#define TFP410_CTL_2_MDI (1<<0) 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci#define TFP410_CTL_3 0x0A 608c2ecf20Sopenharmony_ci#define TFP410_CTL_3_DK_MASK (0x7<<5) 618c2ecf20Sopenharmony_ci#define TFP410_CTL_3_DK (1<<5) 628c2ecf20Sopenharmony_ci#define TFP410_CTL_3_DKEN (1<<4) 638c2ecf20Sopenharmony_ci#define TFP410_CTL_3_CTL_MASK (0x7<<1) 648c2ecf20Sopenharmony_ci#define TFP410_CTL_3_CTL (1<<1) 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci#define TFP410_USERCFG 0x0B 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci#define TFP410_DE_DLY 0x32 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci#define TFP410_DE_CTL 0x33 718c2ecf20Sopenharmony_ci#define TFP410_DE_CTL_DEGEN (1<<6) 728c2ecf20Sopenharmony_ci#define TFP410_DE_CTL_VSPOL (1<<5) 738c2ecf20Sopenharmony_ci#define TFP410_DE_CTL_HSPOL (1<<4) 748c2ecf20Sopenharmony_ci#define TFP410_DE_CTL_DEDLY8 (1<<0) 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci#define TFP410_DE_TOP 0x34 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci#define TFP410_DE_CNT_LO 0x36 798c2ecf20Sopenharmony_ci#define TFP410_DE_CNT_HI 0x37 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci#define TFP410_DE_LIN_LO 0x38 828c2ecf20Sopenharmony_ci#define TFP410_DE_LIN_HI 0x39 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci#define TFP410_H_RES_LO 0x3A 858c2ecf20Sopenharmony_ci#define TFP410_H_RES_HI 0x3B 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci#define TFP410_V_RES_LO 0x3C 888c2ecf20Sopenharmony_ci#define TFP410_V_RES_HI 0x3D 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_cistruct tfp410_priv { 918c2ecf20Sopenharmony_ci bool quiet; 928c2ecf20Sopenharmony_ci}; 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_cistatic bool tfp410_readb(struct intel_dvo_device *dvo, int addr, u8 *ch) 958c2ecf20Sopenharmony_ci{ 968c2ecf20Sopenharmony_ci struct tfp410_priv *tfp = dvo->dev_priv; 978c2ecf20Sopenharmony_ci struct i2c_adapter *adapter = dvo->i2c_bus; 988c2ecf20Sopenharmony_ci u8 out_buf[2]; 998c2ecf20Sopenharmony_ci u8 in_buf[2]; 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci struct i2c_msg msgs[] = { 1028c2ecf20Sopenharmony_ci { 1038c2ecf20Sopenharmony_ci .addr = dvo->slave_addr, 1048c2ecf20Sopenharmony_ci .flags = 0, 1058c2ecf20Sopenharmony_ci .len = 1, 1068c2ecf20Sopenharmony_ci .buf = out_buf, 1078c2ecf20Sopenharmony_ci }, 1088c2ecf20Sopenharmony_ci { 1098c2ecf20Sopenharmony_ci .addr = dvo->slave_addr, 1108c2ecf20Sopenharmony_ci .flags = I2C_M_RD, 1118c2ecf20Sopenharmony_ci .len = 1, 1128c2ecf20Sopenharmony_ci .buf = in_buf, 1138c2ecf20Sopenharmony_ci } 1148c2ecf20Sopenharmony_ci }; 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci out_buf[0] = addr; 1178c2ecf20Sopenharmony_ci out_buf[1] = 0; 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci if (i2c_transfer(adapter, msgs, 2) == 2) { 1208c2ecf20Sopenharmony_ci *ch = in_buf[0]; 1218c2ecf20Sopenharmony_ci return true; 1228c2ecf20Sopenharmony_ci } 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci if (!tfp->quiet) { 1258c2ecf20Sopenharmony_ci DRM_DEBUG_KMS("Unable to read register 0x%02x from %s:%02x.\n", 1268c2ecf20Sopenharmony_ci addr, adapter->name, dvo->slave_addr); 1278c2ecf20Sopenharmony_ci } 1288c2ecf20Sopenharmony_ci return false; 1298c2ecf20Sopenharmony_ci} 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_cistatic bool tfp410_writeb(struct intel_dvo_device *dvo, int addr, u8 ch) 1328c2ecf20Sopenharmony_ci{ 1338c2ecf20Sopenharmony_ci struct tfp410_priv *tfp = dvo->dev_priv; 1348c2ecf20Sopenharmony_ci struct i2c_adapter *adapter = dvo->i2c_bus; 1358c2ecf20Sopenharmony_ci u8 out_buf[2]; 1368c2ecf20Sopenharmony_ci struct i2c_msg msg = { 1378c2ecf20Sopenharmony_ci .addr = dvo->slave_addr, 1388c2ecf20Sopenharmony_ci .flags = 0, 1398c2ecf20Sopenharmony_ci .len = 2, 1408c2ecf20Sopenharmony_ci .buf = out_buf, 1418c2ecf20Sopenharmony_ci }; 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci out_buf[0] = addr; 1448c2ecf20Sopenharmony_ci out_buf[1] = ch; 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci if (i2c_transfer(adapter, &msg, 1) == 1) 1478c2ecf20Sopenharmony_ci return true; 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci if (!tfp->quiet) { 1508c2ecf20Sopenharmony_ci DRM_DEBUG_KMS("Unable to write register 0x%02x to %s:%d.\n", 1518c2ecf20Sopenharmony_ci addr, adapter->name, dvo->slave_addr); 1528c2ecf20Sopenharmony_ci } 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci return false; 1558c2ecf20Sopenharmony_ci} 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_cistatic int tfp410_getid(struct intel_dvo_device *dvo, int addr) 1588c2ecf20Sopenharmony_ci{ 1598c2ecf20Sopenharmony_ci u8 ch1, ch2; 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci if (tfp410_readb(dvo, addr+0, &ch1) && 1628c2ecf20Sopenharmony_ci tfp410_readb(dvo, addr+1, &ch2)) 1638c2ecf20Sopenharmony_ci return ((ch2 << 8) & 0xFF00) | (ch1 & 0x00FF); 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci return -1; 1668c2ecf20Sopenharmony_ci} 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci/* Ti TFP410 driver for chip on i2c bus */ 1698c2ecf20Sopenharmony_cistatic bool tfp410_init(struct intel_dvo_device *dvo, 1708c2ecf20Sopenharmony_ci struct i2c_adapter *adapter) 1718c2ecf20Sopenharmony_ci{ 1728c2ecf20Sopenharmony_ci /* this will detect the tfp410 chip on the specified i2c bus */ 1738c2ecf20Sopenharmony_ci struct tfp410_priv *tfp; 1748c2ecf20Sopenharmony_ci int id; 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci tfp = kzalloc(sizeof(struct tfp410_priv), GFP_KERNEL); 1778c2ecf20Sopenharmony_ci if (tfp == NULL) 1788c2ecf20Sopenharmony_ci return false; 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci dvo->i2c_bus = adapter; 1818c2ecf20Sopenharmony_ci dvo->dev_priv = tfp; 1828c2ecf20Sopenharmony_ci tfp->quiet = true; 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci if ((id = tfp410_getid(dvo, TFP410_VID_LO)) != TFP410_VID) { 1858c2ecf20Sopenharmony_ci DRM_DEBUG_KMS("tfp410 not detected got VID %X: from %s " 1868c2ecf20Sopenharmony_ci "Slave %d.\n", 1878c2ecf20Sopenharmony_ci id, adapter->name, dvo->slave_addr); 1888c2ecf20Sopenharmony_ci goto out; 1898c2ecf20Sopenharmony_ci } 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci if ((id = tfp410_getid(dvo, TFP410_DID_LO)) != TFP410_DID) { 1928c2ecf20Sopenharmony_ci DRM_DEBUG_KMS("tfp410 not detected got DID %X: from %s " 1938c2ecf20Sopenharmony_ci "Slave %d.\n", 1948c2ecf20Sopenharmony_ci id, adapter->name, dvo->slave_addr); 1958c2ecf20Sopenharmony_ci goto out; 1968c2ecf20Sopenharmony_ci } 1978c2ecf20Sopenharmony_ci tfp->quiet = false; 1988c2ecf20Sopenharmony_ci return true; 1998c2ecf20Sopenharmony_ciout: 2008c2ecf20Sopenharmony_ci kfree(tfp); 2018c2ecf20Sopenharmony_ci return false; 2028c2ecf20Sopenharmony_ci} 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_cistatic enum drm_connector_status tfp410_detect(struct intel_dvo_device *dvo) 2058c2ecf20Sopenharmony_ci{ 2068c2ecf20Sopenharmony_ci enum drm_connector_status ret = connector_status_disconnected; 2078c2ecf20Sopenharmony_ci u8 ctl2; 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci if (tfp410_readb(dvo, TFP410_CTL_2, &ctl2)) { 2108c2ecf20Sopenharmony_ci if (ctl2 & TFP410_CTL_2_RSEN) 2118c2ecf20Sopenharmony_ci ret = connector_status_connected; 2128c2ecf20Sopenharmony_ci else 2138c2ecf20Sopenharmony_ci ret = connector_status_disconnected; 2148c2ecf20Sopenharmony_ci } 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci return ret; 2178c2ecf20Sopenharmony_ci} 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_cistatic enum drm_mode_status tfp410_mode_valid(struct intel_dvo_device *dvo, 2208c2ecf20Sopenharmony_ci struct drm_display_mode *mode) 2218c2ecf20Sopenharmony_ci{ 2228c2ecf20Sopenharmony_ci return MODE_OK; 2238c2ecf20Sopenharmony_ci} 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_cistatic void tfp410_mode_set(struct intel_dvo_device *dvo, 2268c2ecf20Sopenharmony_ci const struct drm_display_mode *mode, 2278c2ecf20Sopenharmony_ci const struct drm_display_mode *adjusted_mode) 2288c2ecf20Sopenharmony_ci{ 2298c2ecf20Sopenharmony_ci /* As long as the basics are set up, since we don't have clock dependencies 2308c2ecf20Sopenharmony_ci * in the mode setup, we can just leave the registers alone and everything 2318c2ecf20Sopenharmony_ci * will work fine. 2328c2ecf20Sopenharmony_ci */ 2338c2ecf20Sopenharmony_ci /* don't do much */ 2348c2ecf20Sopenharmony_ci return; 2358c2ecf20Sopenharmony_ci} 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci/* set the tfp410 power state */ 2388c2ecf20Sopenharmony_cistatic void tfp410_dpms(struct intel_dvo_device *dvo, bool enable) 2398c2ecf20Sopenharmony_ci{ 2408c2ecf20Sopenharmony_ci u8 ctl1; 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci if (!tfp410_readb(dvo, TFP410_CTL_1, &ctl1)) 2438c2ecf20Sopenharmony_ci return; 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci if (enable) 2468c2ecf20Sopenharmony_ci ctl1 |= TFP410_CTL_1_PD; 2478c2ecf20Sopenharmony_ci else 2488c2ecf20Sopenharmony_ci ctl1 &= ~TFP410_CTL_1_PD; 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci tfp410_writeb(dvo, TFP410_CTL_1, ctl1); 2518c2ecf20Sopenharmony_ci} 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_cistatic bool tfp410_get_hw_state(struct intel_dvo_device *dvo) 2548c2ecf20Sopenharmony_ci{ 2558c2ecf20Sopenharmony_ci u8 ctl1; 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci if (!tfp410_readb(dvo, TFP410_CTL_1, &ctl1)) 2588c2ecf20Sopenharmony_ci return false; 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci if (ctl1 & TFP410_CTL_1_PD) 2618c2ecf20Sopenharmony_ci return true; 2628c2ecf20Sopenharmony_ci else 2638c2ecf20Sopenharmony_ci return false; 2648c2ecf20Sopenharmony_ci} 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_cistatic void tfp410_dump_regs(struct intel_dvo_device *dvo) 2678c2ecf20Sopenharmony_ci{ 2688c2ecf20Sopenharmony_ci u8 val, val2; 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci tfp410_readb(dvo, TFP410_REV, &val); 2718c2ecf20Sopenharmony_ci DRM_DEBUG_KMS("TFP410_REV: 0x%02X\n", val); 2728c2ecf20Sopenharmony_ci tfp410_readb(dvo, TFP410_CTL_1, &val); 2738c2ecf20Sopenharmony_ci DRM_DEBUG_KMS("TFP410_CTL1: 0x%02X\n", val); 2748c2ecf20Sopenharmony_ci tfp410_readb(dvo, TFP410_CTL_2, &val); 2758c2ecf20Sopenharmony_ci DRM_DEBUG_KMS("TFP410_CTL2: 0x%02X\n", val); 2768c2ecf20Sopenharmony_ci tfp410_readb(dvo, TFP410_CTL_3, &val); 2778c2ecf20Sopenharmony_ci DRM_DEBUG_KMS("TFP410_CTL3: 0x%02X\n", val); 2788c2ecf20Sopenharmony_ci tfp410_readb(dvo, TFP410_USERCFG, &val); 2798c2ecf20Sopenharmony_ci DRM_DEBUG_KMS("TFP410_USERCFG: 0x%02X\n", val); 2808c2ecf20Sopenharmony_ci tfp410_readb(dvo, TFP410_DE_DLY, &val); 2818c2ecf20Sopenharmony_ci DRM_DEBUG_KMS("TFP410_DE_DLY: 0x%02X\n", val); 2828c2ecf20Sopenharmony_ci tfp410_readb(dvo, TFP410_DE_CTL, &val); 2838c2ecf20Sopenharmony_ci DRM_DEBUG_KMS("TFP410_DE_CTL: 0x%02X\n", val); 2848c2ecf20Sopenharmony_ci tfp410_readb(dvo, TFP410_DE_TOP, &val); 2858c2ecf20Sopenharmony_ci DRM_DEBUG_KMS("TFP410_DE_TOP: 0x%02X\n", val); 2868c2ecf20Sopenharmony_ci tfp410_readb(dvo, TFP410_DE_CNT_LO, &val); 2878c2ecf20Sopenharmony_ci tfp410_readb(dvo, TFP410_DE_CNT_HI, &val2); 2888c2ecf20Sopenharmony_ci DRM_DEBUG_KMS("TFP410_DE_CNT: 0x%02X%02X\n", val2, val); 2898c2ecf20Sopenharmony_ci tfp410_readb(dvo, TFP410_DE_LIN_LO, &val); 2908c2ecf20Sopenharmony_ci tfp410_readb(dvo, TFP410_DE_LIN_HI, &val2); 2918c2ecf20Sopenharmony_ci DRM_DEBUG_KMS("TFP410_DE_LIN: 0x%02X%02X\n", val2, val); 2928c2ecf20Sopenharmony_ci tfp410_readb(dvo, TFP410_H_RES_LO, &val); 2938c2ecf20Sopenharmony_ci tfp410_readb(dvo, TFP410_H_RES_HI, &val2); 2948c2ecf20Sopenharmony_ci DRM_DEBUG_KMS("TFP410_H_RES: 0x%02X%02X\n", val2, val); 2958c2ecf20Sopenharmony_ci tfp410_readb(dvo, TFP410_V_RES_LO, &val); 2968c2ecf20Sopenharmony_ci tfp410_readb(dvo, TFP410_V_RES_HI, &val2); 2978c2ecf20Sopenharmony_ci DRM_DEBUG_KMS("TFP410_V_RES: 0x%02X%02X\n", val2, val); 2988c2ecf20Sopenharmony_ci} 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_cistatic void tfp410_destroy(struct intel_dvo_device *dvo) 3018c2ecf20Sopenharmony_ci{ 3028c2ecf20Sopenharmony_ci struct tfp410_priv *tfp = dvo->dev_priv; 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci if (tfp) { 3058c2ecf20Sopenharmony_ci kfree(tfp); 3068c2ecf20Sopenharmony_ci dvo->dev_priv = NULL; 3078c2ecf20Sopenharmony_ci } 3088c2ecf20Sopenharmony_ci} 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ciconst struct intel_dvo_dev_ops tfp410_ops = { 3118c2ecf20Sopenharmony_ci .init = tfp410_init, 3128c2ecf20Sopenharmony_ci .detect = tfp410_detect, 3138c2ecf20Sopenharmony_ci .mode_valid = tfp410_mode_valid, 3148c2ecf20Sopenharmony_ci .mode_set = tfp410_mode_set, 3158c2ecf20Sopenharmony_ci .dpms = tfp410_dpms, 3168c2ecf20Sopenharmony_ci .get_hw_state = tfp410_get_hw_state, 3178c2ecf20Sopenharmony_ci .dump_regs = tfp410_dump_regs, 3188c2ecf20Sopenharmony_ci .destroy = tfp410_destroy, 3198c2ecf20Sopenharmony_ci}; 320