18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * wm9705.c -- Codec driver for Wolfson WM9705 AC97 Codec. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright 2003, 2004, 2005, 2006, 2007 Wolfson Microelectronics PLC. 68c2ecf20Sopenharmony_ci * Author: Liam Girdwood <lrg@slimlogic.co.uk> 78c2ecf20Sopenharmony_ci * Parts Copyright : Ian Molton <spyro@f2s.com> 88c2ecf20Sopenharmony_ci * Andrew Zabolotny <zap@homelink.ru> 98c2ecf20Sopenharmony_ci * Russell King <rmk@arm.linux.org.uk> 108c2ecf20Sopenharmony_ci */ 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include <linux/module.h> 138c2ecf20Sopenharmony_ci#include <linux/moduleparam.h> 148c2ecf20Sopenharmony_ci#include <linux/kernel.h> 158c2ecf20Sopenharmony_ci#include <linux/input.h> 168c2ecf20Sopenharmony_ci#include <linux/delay.h> 178c2ecf20Sopenharmony_ci#include <linux/bitops.h> 188c2ecf20Sopenharmony_ci#include <linux/wm97xx.h> 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci#define TS_NAME "wm97xx" 218c2ecf20Sopenharmony_ci#define WM9705_VERSION "1.00" 228c2ecf20Sopenharmony_ci#define DEFAULT_PRESSURE 0xb0c0 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci/* 258c2ecf20Sopenharmony_ci * Module parameters 268c2ecf20Sopenharmony_ci */ 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci/* 298c2ecf20Sopenharmony_ci * Set current used for pressure measurement. 308c2ecf20Sopenharmony_ci * 318c2ecf20Sopenharmony_ci * Set pil = 2 to use 400uA 328c2ecf20Sopenharmony_ci * pil = 1 to use 200uA and 338c2ecf20Sopenharmony_ci * pil = 0 to disable pressure measurement. 348c2ecf20Sopenharmony_ci * 358c2ecf20Sopenharmony_ci * This is used to increase the range of values returned by the adc 368c2ecf20Sopenharmony_ci * when measureing touchpanel pressure. 378c2ecf20Sopenharmony_ci */ 388c2ecf20Sopenharmony_cistatic int pil; 398c2ecf20Sopenharmony_cimodule_param(pil, int, 0); 408c2ecf20Sopenharmony_ciMODULE_PARM_DESC(pil, "Set current used for pressure measurement."); 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci/* 438c2ecf20Sopenharmony_ci * Set threshold for pressure measurement. 448c2ecf20Sopenharmony_ci * 458c2ecf20Sopenharmony_ci * Pen down pressure below threshold is ignored. 468c2ecf20Sopenharmony_ci */ 478c2ecf20Sopenharmony_cistatic int pressure = DEFAULT_PRESSURE & 0xfff; 488c2ecf20Sopenharmony_cimodule_param(pressure, int, 0); 498c2ecf20Sopenharmony_ciMODULE_PARM_DESC(pressure, "Set threshold for pressure measurement."); 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci/* 528c2ecf20Sopenharmony_ci * Set adc sample delay. 538c2ecf20Sopenharmony_ci * 548c2ecf20Sopenharmony_ci * For accurate touchpanel measurements, some settling time may be 558c2ecf20Sopenharmony_ci * required between the switch matrix applying a voltage across the 568c2ecf20Sopenharmony_ci * touchpanel plate and the ADC sampling the signal. 578c2ecf20Sopenharmony_ci * 588c2ecf20Sopenharmony_ci * This delay can be set by setting delay = n, where n is the array 598c2ecf20Sopenharmony_ci * position of the delay in the array delay_table below. 608c2ecf20Sopenharmony_ci * Long delays > 1ms are supported for completeness, but are not 618c2ecf20Sopenharmony_ci * recommended. 628c2ecf20Sopenharmony_ci */ 638c2ecf20Sopenharmony_cistatic int delay = 4; 648c2ecf20Sopenharmony_cimodule_param(delay, int, 0); 658c2ecf20Sopenharmony_ciMODULE_PARM_DESC(delay, "Set adc sample delay."); 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci/* 688c2ecf20Sopenharmony_ci * Pen detect comparator threshold. 698c2ecf20Sopenharmony_ci * 708c2ecf20Sopenharmony_ci * 0 to Vmid in 15 steps, 0 = use zero power comparator with Vmid threshold 718c2ecf20Sopenharmony_ci * i.e. 1 = Vmid/15 threshold 728c2ecf20Sopenharmony_ci * 15 = Vmid/1 threshold 738c2ecf20Sopenharmony_ci * 748c2ecf20Sopenharmony_ci * Adjust this value if you are having problems with pen detect not 758c2ecf20Sopenharmony_ci * detecting any down events. 768c2ecf20Sopenharmony_ci */ 778c2ecf20Sopenharmony_cistatic int pdd = 8; 788c2ecf20Sopenharmony_cimodule_param(pdd, int, 0); 798c2ecf20Sopenharmony_ciMODULE_PARM_DESC(pdd, "Set pen detect comparator threshold"); 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci/* 828c2ecf20Sopenharmony_ci * Set adc mask function. 838c2ecf20Sopenharmony_ci * 848c2ecf20Sopenharmony_ci * Sources of glitch noise, such as signals driving an LCD display, may feed 858c2ecf20Sopenharmony_ci * through to the touch screen plates and affect measurement accuracy. In 868c2ecf20Sopenharmony_ci * order to minimise this, a signal may be applied to the MASK pin to delay or 878c2ecf20Sopenharmony_ci * synchronise the sampling. 888c2ecf20Sopenharmony_ci * 898c2ecf20Sopenharmony_ci * 0 = No delay or sync 908c2ecf20Sopenharmony_ci * 1 = High on pin stops conversions 918c2ecf20Sopenharmony_ci * 2 = Edge triggered, edge on pin delays conversion by delay param (above) 928c2ecf20Sopenharmony_ci * 3 = Edge triggered, edge on pin starts conversion after delay param 938c2ecf20Sopenharmony_ci */ 948c2ecf20Sopenharmony_cistatic int mask; 958c2ecf20Sopenharmony_cimodule_param(mask, int, 0); 968c2ecf20Sopenharmony_ciMODULE_PARM_DESC(mask, "Set adc mask function."); 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci/* 998c2ecf20Sopenharmony_ci * ADC sample delay times in uS 1008c2ecf20Sopenharmony_ci */ 1018c2ecf20Sopenharmony_cistatic const int delay_table[] = { 1028c2ecf20Sopenharmony_ci 21, /* 1 AC97 Link frames */ 1038c2ecf20Sopenharmony_ci 42, /* 2 */ 1048c2ecf20Sopenharmony_ci 84, /* 4 */ 1058c2ecf20Sopenharmony_ci 167, /* 8 */ 1068c2ecf20Sopenharmony_ci 333, /* 16 */ 1078c2ecf20Sopenharmony_ci 667, /* 32 */ 1088c2ecf20Sopenharmony_ci 1000, /* 48 */ 1098c2ecf20Sopenharmony_ci 1333, /* 64 */ 1108c2ecf20Sopenharmony_ci 2000, /* 96 */ 1118c2ecf20Sopenharmony_ci 2667, /* 128 */ 1128c2ecf20Sopenharmony_ci 3333, /* 160 */ 1138c2ecf20Sopenharmony_ci 4000, /* 192 */ 1148c2ecf20Sopenharmony_ci 4667, /* 224 */ 1158c2ecf20Sopenharmony_ci 5333, /* 256 */ 1168c2ecf20Sopenharmony_ci 6000, /* 288 */ 1178c2ecf20Sopenharmony_ci 0 /* No delay, switch matrix always on */ 1188c2ecf20Sopenharmony_ci}; 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci/* 1218c2ecf20Sopenharmony_ci * Delay after issuing a POLL command. 1228c2ecf20Sopenharmony_ci * 1238c2ecf20Sopenharmony_ci * The delay is 3 AC97 link frames + the touchpanel settling delay 1248c2ecf20Sopenharmony_ci */ 1258c2ecf20Sopenharmony_cistatic inline void poll_delay(int d) 1268c2ecf20Sopenharmony_ci{ 1278c2ecf20Sopenharmony_ci udelay(3 * AC97_LINK_FRAME + delay_table[d]); 1288c2ecf20Sopenharmony_ci} 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci/* 1318c2ecf20Sopenharmony_ci * set up the physical settings of the WM9705 1328c2ecf20Sopenharmony_ci */ 1338c2ecf20Sopenharmony_cistatic void wm9705_phy_init(struct wm97xx *wm) 1348c2ecf20Sopenharmony_ci{ 1358c2ecf20Sopenharmony_ci u16 dig1 = 0, dig2 = WM97XX_RPR; 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci /* 1388c2ecf20Sopenharmony_ci * mute VIDEO and AUX as they share X and Y touchscreen 1398c2ecf20Sopenharmony_ci * inputs on the WM9705 1408c2ecf20Sopenharmony_ci */ 1418c2ecf20Sopenharmony_ci wm97xx_reg_write(wm, AC97_AUX, 0x8000); 1428c2ecf20Sopenharmony_ci wm97xx_reg_write(wm, AC97_VIDEO, 0x8000); 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci /* touchpanel pressure current*/ 1458c2ecf20Sopenharmony_ci if (pil == 2) { 1468c2ecf20Sopenharmony_ci dig2 |= WM9705_PIL; 1478c2ecf20Sopenharmony_ci dev_dbg(wm->dev, 1488c2ecf20Sopenharmony_ci "setting pressure measurement current to 400uA."); 1498c2ecf20Sopenharmony_ci } else if (pil) 1508c2ecf20Sopenharmony_ci dev_dbg(wm->dev, 1518c2ecf20Sopenharmony_ci "setting pressure measurement current to 200uA."); 1528c2ecf20Sopenharmony_ci if (!pil) 1538c2ecf20Sopenharmony_ci pressure = 0; 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci /* polling mode sample settling delay */ 1568c2ecf20Sopenharmony_ci if (delay != 4) { 1578c2ecf20Sopenharmony_ci if (delay < 0 || delay > 15) { 1588c2ecf20Sopenharmony_ci dev_dbg(wm->dev, "supplied delay out of range."); 1598c2ecf20Sopenharmony_ci delay = 4; 1608c2ecf20Sopenharmony_ci } 1618c2ecf20Sopenharmony_ci } 1628c2ecf20Sopenharmony_ci dig1 &= 0xff0f; 1638c2ecf20Sopenharmony_ci dig1 |= WM97XX_DELAY(delay); 1648c2ecf20Sopenharmony_ci dev_dbg(wm->dev, "setting adc sample delay to %d u Secs.", 1658c2ecf20Sopenharmony_ci delay_table[delay]); 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci /* WM9705 pdd */ 1688c2ecf20Sopenharmony_ci dig2 |= (pdd & 0x000f); 1698c2ecf20Sopenharmony_ci dev_dbg(wm->dev, "setting pdd to Vmid/%d", 1 - (pdd & 0x000f)); 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci /* mask */ 1728c2ecf20Sopenharmony_ci dig2 |= ((mask & 0x3) << 4); 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, dig1); 1758c2ecf20Sopenharmony_ci wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2); 1768c2ecf20Sopenharmony_ci} 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_cistatic void wm9705_dig_enable(struct wm97xx *wm, int enable) 1798c2ecf20Sopenharmony_ci{ 1808c2ecf20Sopenharmony_ci if (enable) { 1818c2ecf20Sopenharmony_ci wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, 1828c2ecf20Sopenharmony_ci wm->dig[2] | WM97XX_PRP_DET_DIG); 1838c2ecf20Sopenharmony_ci wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); /* dummy read */ 1848c2ecf20Sopenharmony_ci } else 1858c2ecf20Sopenharmony_ci wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, 1868c2ecf20Sopenharmony_ci wm->dig[2] & ~WM97XX_PRP_DET_DIG); 1878c2ecf20Sopenharmony_ci} 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_cistatic void wm9705_aux_prepare(struct wm97xx *wm) 1908c2ecf20Sopenharmony_ci{ 1918c2ecf20Sopenharmony_ci memcpy(wm->dig_save, wm->dig, sizeof(wm->dig)); 1928c2ecf20Sopenharmony_ci wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, 0); 1938c2ecf20Sopenharmony_ci wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, WM97XX_PRP_DET_DIG); 1948c2ecf20Sopenharmony_ci} 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_cistatic void wm9705_dig_restore(struct wm97xx *wm) 1978c2ecf20Sopenharmony_ci{ 1988c2ecf20Sopenharmony_ci wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, wm->dig_save[1]); 1998c2ecf20Sopenharmony_ci wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, wm->dig_save[2]); 2008c2ecf20Sopenharmony_ci} 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_cistatic inline int is_pden(struct wm97xx *wm) 2038c2ecf20Sopenharmony_ci{ 2048c2ecf20Sopenharmony_ci return wm->dig[2] & WM9705_PDEN; 2058c2ecf20Sopenharmony_ci} 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci/* 2088c2ecf20Sopenharmony_ci * Read a sample from the WM9705 adc in polling mode. 2098c2ecf20Sopenharmony_ci */ 2108c2ecf20Sopenharmony_cistatic int wm9705_poll_sample(struct wm97xx *wm, int adcsel, int *sample) 2118c2ecf20Sopenharmony_ci{ 2128c2ecf20Sopenharmony_ci int timeout = 5 * delay; 2138c2ecf20Sopenharmony_ci bool wants_pen = adcsel & WM97XX_PEN_DOWN; 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci if (wants_pen && !wm->pen_probably_down) { 2168c2ecf20Sopenharmony_ci u16 data = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); 2178c2ecf20Sopenharmony_ci if (!(data & WM97XX_PEN_DOWN)) 2188c2ecf20Sopenharmony_ci return RC_PENUP; 2198c2ecf20Sopenharmony_ci wm->pen_probably_down = 1; 2208c2ecf20Sopenharmony_ci } 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci /* set up digitiser */ 2238c2ecf20Sopenharmony_ci if (wm->mach_ops && wm->mach_ops->pre_sample) 2248c2ecf20Sopenharmony_ci wm->mach_ops->pre_sample(adcsel); 2258c2ecf20Sopenharmony_ci wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, (adcsel & WM97XX_ADCSEL_MASK) 2268c2ecf20Sopenharmony_ci | WM97XX_POLL | WM97XX_DELAY(delay)); 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci /* wait 3 AC97 time slots + delay for conversion */ 2298c2ecf20Sopenharmony_ci poll_delay(delay); 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci /* wait for POLL to go low */ 2328c2ecf20Sopenharmony_ci while ((wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER1) & WM97XX_POLL) 2338c2ecf20Sopenharmony_ci && timeout) { 2348c2ecf20Sopenharmony_ci udelay(AC97_LINK_FRAME); 2358c2ecf20Sopenharmony_ci timeout--; 2368c2ecf20Sopenharmony_ci } 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci if (timeout == 0) { 2398c2ecf20Sopenharmony_ci /* If PDEN is set, we can get a timeout when pen goes up */ 2408c2ecf20Sopenharmony_ci if (is_pden(wm)) 2418c2ecf20Sopenharmony_ci wm->pen_probably_down = 0; 2428c2ecf20Sopenharmony_ci else 2438c2ecf20Sopenharmony_ci dev_dbg(wm->dev, "adc sample timeout"); 2448c2ecf20Sopenharmony_ci return RC_PENUP; 2458c2ecf20Sopenharmony_ci } 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci *sample = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); 2488c2ecf20Sopenharmony_ci if (wm->mach_ops && wm->mach_ops->post_sample) 2498c2ecf20Sopenharmony_ci wm->mach_ops->post_sample(adcsel); 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci /* check we have correct sample */ 2528c2ecf20Sopenharmony_ci if ((*sample ^ adcsel) & WM97XX_ADCSEL_MASK) { 2538c2ecf20Sopenharmony_ci dev_dbg(wm->dev, "adc wrong sample, wanted %x got %x", 2548c2ecf20Sopenharmony_ci adcsel & WM97XX_ADCSEL_MASK, 2558c2ecf20Sopenharmony_ci *sample & WM97XX_ADCSEL_MASK); 2568c2ecf20Sopenharmony_ci return RC_PENUP; 2578c2ecf20Sopenharmony_ci } 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_ci if (wants_pen && !(*sample & WM97XX_PEN_DOWN)) { 2608c2ecf20Sopenharmony_ci wm->pen_probably_down = 0; 2618c2ecf20Sopenharmony_ci return RC_PENUP; 2628c2ecf20Sopenharmony_ci } 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci return RC_VALID; 2658c2ecf20Sopenharmony_ci} 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci/* 2688c2ecf20Sopenharmony_ci * Sample the WM9705 touchscreen in polling mode 2698c2ecf20Sopenharmony_ci */ 2708c2ecf20Sopenharmony_cistatic int wm9705_poll_touch(struct wm97xx *wm, struct wm97xx_data *data) 2718c2ecf20Sopenharmony_ci{ 2728c2ecf20Sopenharmony_ci int rc; 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_ci rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_X | WM97XX_PEN_DOWN, &data->x); 2758c2ecf20Sopenharmony_ci if (rc != RC_VALID) 2768c2ecf20Sopenharmony_ci return rc; 2778c2ecf20Sopenharmony_ci rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_Y | WM97XX_PEN_DOWN, &data->y); 2788c2ecf20Sopenharmony_ci if (rc != RC_VALID) 2798c2ecf20Sopenharmony_ci return rc; 2808c2ecf20Sopenharmony_ci if (pil) { 2818c2ecf20Sopenharmony_ci rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_PRES | WM97XX_PEN_DOWN, &data->p); 2828c2ecf20Sopenharmony_ci if (rc != RC_VALID) 2838c2ecf20Sopenharmony_ci return rc; 2848c2ecf20Sopenharmony_ci } else 2858c2ecf20Sopenharmony_ci data->p = DEFAULT_PRESSURE; 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_ci return RC_VALID; 2888c2ecf20Sopenharmony_ci} 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci/* 2918c2ecf20Sopenharmony_ci * Enable WM9705 continuous mode, i.e. touch data is streamed across 2928c2ecf20Sopenharmony_ci * an AC97 slot 2938c2ecf20Sopenharmony_ci */ 2948c2ecf20Sopenharmony_cistatic int wm9705_acc_enable(struct wm97xx *wm, int enable) 2958c2ecf20Sopenharmony_ci{ 2968c2ecf20Sopenharmony_ci u16 dig1, dig2; 2978c2ecf20Sopenharmony_ci int ret = 0; 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_ci dig1 = wm->dig[1]; 3008c2ecf20Sopenharmony_ci dig2 = wm->dig[2]; 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci if (enable) { 3038c2ecf20Sopenharmony_ci /* continuous mode */ 3048c2ecf20Sopenharmony_ci if (wm->mach_ops->acc_startup && 3058c2ecf20Sopenharmony_ci (ret = wm->mach_ops->acc_startup(wm)) < 0) 3068c2ecf20Sopenharmony_ci return ret; 3078c2ecf20Sopenharmony_ci dig1 &= ~(WM97XX_CM_RATE_MASK | WM97XX_ADCSEL_MASK | 3088c2ecf20Sopenharmony_ci WM97XX_DELAY_MASK | WM97XX_SLT_MASK); 3098c2ecf20Sopenharmony_ci dig1 |= WM97XX_CTC | WM97XX_COO | WM97XX_SLEN | 3108c2ecf20Sopenharmony_ci WM97XX_DELAY(delay) | 3118c2ecf20Sopenharmony_ci WM97XX_SLT(wm->acc_slot) | 3128c2ecf20Sopenharmony_ci WM97XX_RATE(wm->acc_rate); 3138c2ecf20Sopenharmony_ci if (pil) 3148c2ecf20Sopenharmony_ci dig1 |= WM97XX_ADCSEL_PRES; 3158c2ecf20Sopenharmony_ci dig2 |= WM9705_PDEN; 3168c2ecf20Sopenharmony_ci } else { 3178c2ecf20Sopenharmony_ci dig1 &= ~(WM97XX_CTC | WM97XX_COO | WM97XX_SLEN); 3188c2ecf20Sopenharmony_ci dig2 &= ~WM9705_PDEN; 3198c2ecf20Sopenharmony_ci if (wm->mach_ops->acc_shutdown) 3208c2ecf20Sopenharmony_ci wm->mach_ops->acc_shutdown(wm); 3218c2ecf20Sopenharmony_ci } 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_ci wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, dig1); 3248c2ecf20Sopenharmony_ci wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2); 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci return ret; 3278c2ecf20Sopenharmony_ci} 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_cistruct wm97xx_codec_drv wm9705_codec = { 3308c2ecf20Sopenharmony_ci .id = WM9705_ID2, 3318c2ecf20Sopenharmony_ci .name = "wm9705", 3328c2ecf20Sopenharmony_ci .poll_sample = wm9705_poll_sample, 3338c2ecf20Sopenharmony_ci .poll_touch = wm9705_poll_touch, 3348c2ecf20Sopenharmony_ci .acc_enable = wm9705_acc_enable, 3358c2ecf20Sopenharmony_ci .phy_init = wm9705_phy_init, 3368c2ecf20Sopenharmony_ci .dig_enable = wm9705_dig_enable, 3378c2ecf20Sopenharmony_ci .dig_restore = wm9705_dig_restore, 3388c2ecf20Sopenharmony_ci .aux_prepare = wm9705_aux_prepare, 3398c2ecf20Sopenharmony_ci}; 3408c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(wm9705_codec); 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_ci/* Module information */ 3438c2ecf20Sopenharmony_ciMODULE_AUTHOR("Liam Girdwood <lrg@slimlogic.co.uk>"); 3448c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("WM9705 Touch Screen Driver"); 3458c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 346