sii9234.c 85 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202
  1. /*
  2. * Copyright (C) 2011 Samsung Electronics
  3. *
  4. * Authors: Adam Hampson <ahampson@sta.samsung.com>
  5. * Erik Gilling <konkers@android.com>
  6. *
  7. * Additional contributions by : Shankar Bandal <shankar.b@samsung.com>
  8. * Dharam Kumar <dharam.kr@samsung.com>
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation; either version 2 of the License, or
  13. * (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program; if not, write to the Free Software
  22. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  23. *
  24. */
  25. #include <linux/delay.h>
  26. #include <linux/err.h>
  27. #include <linux/gpio.h>
  28. #include <linux/i2c.h>
  29. #include <linux/interrupt.h>
  30. #include <linux/irq.h>
  31. #include <linux/kernel.h>
  32. #include <linux/module.h>
  33. #include <linux/mutex.h>
  34. #include <linux/platform_device.h>
  35. #include <linux/sii9234.h>
  36. #include <linux/slab.h>
  37. #include <linux/wait.h>
  38. #include <linux/file.h>
  39. #include <linux/uaccess.h>
  40. #include <linux/proc_fs.h>
  41. #include <mach/gpio.h>
  42. #include "sii9234_driver.h"
  43. /* #define pr_debug pr_info */
  44. static int en_irq;
  45. #undef __SII9234_MUTEX_DEBUG__
  46. #undef __SII9234_DEBUG__
  47. #ifdef __SII9234_MUTEX_DEBUG__
  48. static int g_mutex_cnt;
  49. static int g_cbus_mutex_cnt;
  50. #define sii9234_mutex_lock(prm) \
  51. do { \
  52. pr_debug("%s(%d)mutex++:%d\n", __func__, __LINE__,\
  53. ++g_mutex_cnt); mutex_lock(prm); pr_debug("%s(%d)mutex--:%d\n",\
  54. __func__, __LINE__, g_mutex_cnt);\
  55. } while (0)
  56. #define sii9234_mutex_unlock(prm) \
  57. do { \
  58. pr_debug("%s(%d) mutex_unlock:%d\n", __func__, __LINE__,\
  59. --g_mutex_cnt); mutex_unlock(prm); \
  60. } while (0)
  61. #define sii9234_cbus_mutex_lock(prm) \
  62. do { \
  63. pr_debug("%s(%d) cbus mutex++:%d\n", __func__, __LINE__,\
  64. ++g_cbus_mutex_cnt); mutex_lock(prm);\
  65. pr_debug("%s(%d) cbus mutex--:%d\n",\
  66. __func__, __LINE__, g_cbus_mutex_cnt);\
  67. } while (0)
  68. #define sii9234_cbus_mutex_unlock(prm) \
  69. do { \
  70. pr_debug("%s(%d) cbus mutex_unlock:%d\n",\
  71. __func__, __LINE__, --g_cbus_mutex_cnt); mutex_unlock(prm);\
  72. } while (0)
  73. #endif
  74. #define sii9234_mutex_lock(prm) mutex_lock(prm);
  75. #define sii9234_mutex_unlock(prm) mutex_unlock(prm);
  76. #define sii9234_cbus_mutex_lock(prm) mutex_lock(prm);
  77. #define sii9234_cbus_mutex_unlock(prm) mutex_unlock(prm);
  78. #define sii9234_enable_irq() \
  79. do { \
  80. if (atomic_read(&sii9234->is_irq_enabled) == false) { \
  81. atomic_set(&sii9234->is_irq_enabled, true); \
  82. enable_irq(sii9234->pdata->mhl_tx_client->irq); \
  83. pr_debug("%s():enable_irq(%d)\n", __func__, ++en_irq);\
  84. } else { \
  85. pr_debug("%s():irq is already enabled(%d)\n", __func__,\
  86. en_irq); \
  87. } \
  88. } while (0)
  89. #define sii9234_disable_irq() \
  90. do { \
  91. if (atomic_read(&sii9234->is_irq_enabled) == true) { \
  92. atomic_set(&sii9234->is_irq_enabled, false); \
  93. disable_irq_nosync(sii9234->pdata->mhl_tx_client->irq);\
  94. pr_debug("%s():disable_irq(%d)\n", __func__, --en_irq);\
  95. } else { \
  96. pr_debug("%s():irq is already disable(%d)\n", __func__,\
  97. en_irq); \
  98. } \
  99. } while (0)
  100. #ifdef CONFIG_MHL_SWING_LEVEL
  101. #include <linux/ctype.h>
  102. #endif
  103. #undef __CONFIG_RSEN_LOST_PATCH__
  104. #undef __CONFIG_USE_TIMER__
  105. static u8 sii9234_tmds_control(struct sii9234_data *sii9234, bool enable);
  106. static bool cbus_command_request(struct sii9234_data *sii9234,
  107. enum cbus_command command,
  108. u8 offset, u8 data);
  109. #ifndef CONFIG_MHL_NEW_CBUS_MSC_CMD
  110. static void cbus_command_response(struct sii9234_data *sii9234);
  111. #endif
  112. static irqreturn_t sii9234_irq_thread(int irq, void *data);
  113. static struct cbus_packet cbus_pkt_buf[CBUS_PKT_BUF_COUNT];
  114. static void sii9234_detection_callback(struct work_struct *work);
  115. #ifdef CONFIG_MHL_NEW_CBUS_MSC_CMD
  116. LIST_HEAD(g_msc_packet_list);
  117. static int g_list_cnt;
  118. static struct workqueue_struct *sii9234_msc_wq;
  119. #endif
  120. #ifdef MHL_SS_FACTORY
  121. struct class *sec_mhl;
  122. EXPORT_SYMBOL(sec_mhl);
  123. #endif
  124. #ifdef CONFIG_MHL_D3_SUPPORT
  125. static void goto_d3(struct work_struct *work);
  126. #endif
  127. #ifdef __CONFIG_USE_TIMER__
  128. static int cbus_command_abort_state;
  129. #endif
  130. static int sii9234_callback_sched;
  131. static int d3_mode_rgnd_state;
  132. #ifdef CONFIG_MHL_SWING_LEVEL
  133. static ssize_t sii9234_swing_test_show(struct device *dev,
  134. struct device_attribute *attr, const char *buf, size_t size)
  135. {
  136. struct sii9234_data *sii9234 = dev_get_drvdata(sii9244_mhldev);
  137. return snprintf(buf, "mhl_show_value : 0x%x\n",
  138. sii9234->pdata->swing_level);
  139. }
  140. static ssize_t sii9234_swing_test_store(struct device *dev,
  141. struct device_attribute *attr,
  142. const char *buf, size_t size)
  143. {
  144. struct sii9234_data *sii9234 = dev_get_drvdata(sii9244_mhldev);
  145. char temp[4] = { 0, };
  146. const char *p = buf;
  147. int data, clk;
  148. unsigned int value;
  149. while (*p != '\0') {
  150. if (!isspace(*p))
  151. strlcat(temp, p, 1);
  152. p++;
  153. }
  154. if (strlen(temp) != 2)
  155. return -EINVAL;
  156. kstrtoul(temp, 10, &value);
  157. data = value / 10;
  158. clk = value % 10;
  159. sii9234->pdata->swing_level = 0xc0;
  160. sii9234->pdata->swing_level = sii9234->pdata->swing_level
  161. | (data << 3) | clk;
  162. snprintf(buf, "mhl_store_value : 0x%x\n", sii9234->pdata->swing_level);
  163. return size;
  164. }
  165. static CLASS_ATTR(swing, 0664,
  166. sii9234_swing_test_show, sii9234_swing_test_store);
  167. #endif
  168. u8 mhl_onoff_ex(bool onoff)
  169. {
  170. struct sii9234_data *sii9234 = dev_get_drvdata(sii9244_mhldev);
  171. if (!sii9234 || !sii9234->pdata) {
  172. pr_info("mhl_onoff_ex: getting resource is failed\n");
  173. return 2;
  174. }
  175. if (sii9234->pdata->power_state == onoff) {
  176. pr_info("mhl_onoff_ex: mhl already %s\n", onoff ? "on" : "off");
  177. return 2;
  178. }
  179. sii9234->pdata->power_state = onoff; /*save power state*/
  180. if (sii9234->pdata->mhl_sel)
  181. sii9234->pdata->mhl_sel(onoff);
  182. if (onoff) {
  183. if (sii9234->pdata->hw_onoff)
  184. sii9234->pdata->hw_onoff(1);
  185. if (sii9234->pdata->hw_reset)
  186. sii9234->pdata->hw_reset();
  187. #ifdef CONFIG_MHL_D3_SUPPORT
  188. detached_status = 0;
  189. d3_mode_rgnd_state = 0;
  190. goto_d3(NULL);
  191. return 2;
  192. #else
  193. sii9234_detection_callback(NULL);
  194. #endif
  195. } else {
  196. sii9234_cancel_callback();
  197. if (sii9234->pdata->hw_onoff)
  198. sii9234->pdata->hw_onoff(0);
  199. }
  200. return sii9234->rgnd;
  201. }
  202. EXPORT_SYMBOL(mhl_onoff_ex);
  203. static int mhl_tx_write_reg(struct sii9234_data *sii9234, unsigned int offset,
  204. u8 value)
  205. {
  206. int ret;
  207. ret = i2c_smbus_write_byte_data(sii9234->pdata->mhl_tx_client, offset,
  208. value);
  209. if (ret < 0)
  210. pr_err("[ERROR] sii9234 : %s(0x%02x, 0x%02x)\n", __func__,
  211. offset, value);
  212. return ret;
  213. }
  214. static int mhl_tx_read_reg(struct sii9234_data *sii9234, unsigned int offset,
  215. u8 *value)
  216. {
  217. int ret;
  218. if (!value)
  219. return -EINVAL;
  220. ret = i2c_smbus_write_byte(sii9234->pdata->mhl_tx_client, offset);
  221. if (ret < 0) {
  222. pr_err("[ERROR] sii9234 : %s(0x%02x)\n", __func__, offset);
  223. return ret;
  224. }
  225. ret = i2c_smbus_read_byte(sii9234->pdata->mhl_tx_client);
  226. if (ret < 0) {
  227. pr_err("[ERROR] sii9234 : %s(0x%02x)\n", __func__, offset);
  228. return ret;
  229. }
  230. *value = ret & 0x000000FF;
  231. return 0;
  232. }
  233. static int mhl_tx_set_reg(struct sii9234_data *sii9234, unsigned int offset,
  234. u8 mask)
  235. {
  236. int ret;
  237. u8 value;
  238. ret = mhl_tx_read_reg(sii9234, offset, &value);
  239. if (ret < 0) {
  240. pr_err("[ERROR] sii9234 : %s(0x%02x, 0x%02x)\n", __func__,
  241. offset, mask);
  242. return ret;
  243. }
  244. value |= mask;
  245. return mhl_tx_write_reg(sii9234, offset, value);
  246. }
  247. static int mhl_tx_clear_reg(struct sii9234_data *sii9234, unsigned int offset,
  248. u8 mask)
  249. {
  250. int ret;
  251. u8 value;
  252. ret = mhl_tx_read_reg(sii9234, offset, &value);
  253. if (ret < 0) {
  254. pr_err("[ERROR] sii9234 : %s(0x%02x, 0x%02x)\n", __func__,
  255. offset, mask);
  256. return ret;
  257. }
  258. value &= ~mask;
  259. ret = mhl_tx_write_reg(sii9234, offset, value);
  260. if (ret < 0)
  261. pr_err("[ERROR] sii9234 : %s(0x%02x, 0x%02x)\n", __func__,
  262. offset, mask);
  263. return ret;
  264. }
  265. static int tpi_write_reg(struct sii9234_data *sii9234, unsigned int offset,
  266. u8 value)
  267. {
  268. int ret = 0;
  269. ret = i2c_smbus_write_byte_data(sii9234->pdata->tpi_client, offset,
  270. value);
  271. if (ret < 0)
  272. pr_err("[ERROR] sii9234 : %s(0x%02x, 0x%02x)\n", __func__,
  273. offset, value);
  274. return ret;
  275. }
  276. #ifdef CONFIG_MHL_D3_SUPPORT
  277. static int tpi_read_reg(struct sii9234_data *sii9234, unsigned int offset,
  278. u8 *value)
  279. {
  280. int ret;
  281. if (!value)
  282. return -EINVAL;
  283. ret = i2c_smbus_write_byte(sii9234->pdata->tpi_client, offset);
  284. if (ret < 0) {
  285. pr_err("[ERROR] sii9234 : %s(0x%02x)\n", __func__, offset);
  286. return ret;
  287. }
  288. ret = i2c_smbus_read_byte(sii9234->pdata->tpi_client);
  289. if (ret < 0) {
  290. pr_err("[ERROR] sii9234 : %s(0x%02x)\n", __func__, offset);
  291. return ret;
  292. }
  293. *value = ret & 0x000000FF;
  294. return 0;
  295. }
  296. #endif
  297. static int hdmi_rx_write_reg(struct sii9234_data *sii9234, unsigned int offset,
  298. u8 value)
  299. {
  300. int ret;
  301. ret = i2c_smbus_write_byte_data(sii9234->pdata->hdmi_rx_client, offset,
  302. value);
  303. if (ret < 0)
  304. pr_err("[ERROR] sii9234 : %s(0x%02x, 0x%02x)\n", __func__,
  305. offset, value);
  306. return ret;
  307. }
  308. static int cbus_write_reg(struct sii9234_data *sii9234, unsigned int offset,
  309. u8 value)
  310. {
  311. return i2c_smbus_write_byte_data(sii9234->pdata->cbus_client, offset,
  312. value);
  313. }
  314. static int cbus_read_reg(struct sii9234_data *sii9234, unsigned int offset,
  315. u8 *value)
  316. {
  317. int ret;
  318. if (!value)
  319. return -EINVAL;
  320. ret = i2c_smbus_write_byte(sii9234->pdata->cbus_client, offset);
  321. if (ret < 0) {
  322. pr_err("[ERROR] sii9234 : %s(0x%02x)\n", __func__, offset);
  323. return ret;
  324. }
  325. ret = i2c_smbus_read_byte(sii9234->pdata->cbus_client);
  326. if (ret < 0) {
  327. pr_err("[ERROR] sii9234 : %s(0x%02x)\n", __func__, offset);
  328. return ret;
  329. }
  330. *value = ret & 0x000000FF;
  331. return 0;
  332. }
  333. static int cbus_set_reg(struct sii9234_data *sii9234, unsigned int offset,
  334. u8 mask)
  335. {
  336. int ret;
  337. u8 value;
  338. ret = cbus_read_reg(sii9234, offset, &value);
  339. if (ret < 0) {
  340. pr_err("[ERROR] sii9234 : %s(0x%02x, 0x%02x)\n", __func__,
  341. offset, mask);
  342. return ret;
  343. }
  344. value |= mask;
  345. return cbus_write_reg(sii9234, offset, value);
  346. }
  347. static int mhl_wake_toggle(struct sii9234_data *sii9234,
  348. unsigned long high_period,
  349. unsigned long low_period)
  350. {
  351. int ret;
  352. /* These bits are not documented. */
  353. ret = mhl_tx_set_reg(sii9234, MHL_TX_DISC_CTRL7_REG, (1<<7) | (1<<6));
  354. if (ret < 0)
  355. return ret;
  356. msleep(high_period);
  357. ret = mhl_tx_clear_reg(sii9234, MHL_TX_DISC_CTRL7_REG, (1<<7) | (1<<6));
  358. if (ret < 0)
  359. return ret;
  360. usleep_range(low_period * USEC_PER_MSEC, low_period * USEC_PER_MSEC);
  361. return 0;
  362. }
  363. static int mhl_send_wake_pulses(struct sii9234_data *sii9234)
  364. {
  365. int ret;
  366. ret = mhl_wake_toggle(sii9234, T_SRC_WAKE_PULSE_WIDTH_1,
  367. T_SRC_WAKE_PULSE_WIDTH_1);
  368. if (ret < 0)
  369. return ret;
  370. ret = mhl_wake_toggle(sii9234, T_SRC_WAKE_PULSE_WIDTH_1,
  371. T_SRC_WAKE_PULSE_WIDTH_2);
  372. if (ret < 0)
  373. return ret;
  374. ret = mhl_wake_toggle(sii9234, T_SRC_WAKE_PULSE_WIDTH_1,
  375. T_SRC_WAKE_PULSE_WIDTH_1);
  376. if (ret < 0)
  377. return ret;
  378. ret = mhl_wake_toggle(sii9234, T_SRC_WAKE_PULSE_WIDTH_1,
  379. T_SRC_WAKE_TO_DISCOVER);
  380. if (ret < 0)
  381. return ret;
  382. return 0;
  383. }
  384. static int sii9234_cbus_reset(struct sii9234_data *sii9234)
  385. {
  386. int ret;
  387. u8 idx;
  388. /* Reset CBUS */
  389. ret = mhl_tx_set_reg(sii9234, MHL_TX_SRST, 0x03);
  390. if (ret < 0)
  391. return ret;
  392. msleep(T_SRC_CBUS_DEGLITCH);
  393. ret = mhl_tx_clear_reg(sii9234, MHL_TX_SRST, 0x03);
  394. if (ret < 0)
  395. return ret;
  396. for (idx = 0; idx < 4; idx++) {
  397. /* Enable WRITE_STAT interrupt for writes to all
  398. 4 MSC Status registers.*/
  399. ret = cbus_write_reg(sii9234, 0xE0 + idx, 0xF2);
  400. if (ret < 0)
  401. return ret;
  402. /*Enable SET_INT interrupt for writes to all
  403. 4 MSC Interrupt registers.*/
  404. ret = cbus_write_reg(sii9234, 0xF0 + idx, 0xF2);
  405. if (ret < 0)
  406. return ret;
  407. }
  408. return 0;
  409. }
  410. /* require to chek mhl imformation of samsung in cbus_init_register*/
  411. static int sii9234_cbus_init(struct sii9234_data *sii9234)
  412. {
  413. u8 value;
  414. int ret;
  415. ret = cbus_write_reg(sii9234, 0x07, 0xF2);
  416. if (ret < 0)
  417. goto i2c_error_exit;
  418. ret = cbus_write_reg(sii9234, 0x40, 0x03);
  419. if (ret < 0)
  420. goto i2c_error_exit;
  421. ret = cbus_write_reg(sii9234, 0x42, 0x06);
  422. if (ret < 0)
  423. goto i2c_error_exit;
  424. ret = cbus_write_reg(sii9234, 0x36, 0x0C);
  425. if (ret < 0)
  426. goto i2c_error_exit;
  427. ret = cbus_write_reg(sii9234, 0x3D, 0xFD);
  428. if (ret < 0)
  429. goto i2c_error_exit;
  430. ret = cbus_write_reg(sii9234, 0x1C, 0x01);
  431. if (ret < 0)
  432. goto i2c_error_exit;
  433. ret = cbus_write_reg(sii9234, 0x1D, 0x0F);
  434. if (ret < 0)
  435. goto i2c_error_exit;
  436. ret = cbus_write_reg(sii9234, 0x44, 0x02);
  437. if (ret < 0)
  438. goto i2c_error_exit;
  439. /* Setup our devcap*/
  440. ret = cbus_write_reg(sii9234, 0x80, 0x00);/*To meet cts 6.3.10.1 spec*/
  441. if (ret < 0)
  442. goto i2c_error_exit;
  443. ret = cbus_write_reg(sii9234, 0x81, 0x11);/*mhl version 1.1*/
  444. if (ret < 0)
  445. goto i2c_error_exit;
  446. ret = cbus_write_reg(sii9234, 0x82, 0x02);
  447. if (ret < 0)
  448. goto i2c_error_exit;
  449. ret = cbus_write_reg(sii9234, 0x83, 0x01);/*adopter_id 0x141*/
  450. if (ret < 0)
  451. goto i2c_error_exit;
  452. ret = cbus_write_reg(sii9234, 0x84, 0x41);/*adopter_id 0x141*/
  453. if (ret < 0)
  454. goto i2c_error_exit;
  455. ret = cbus_write_reg(sii9234, 0x85, 0x01);/*ONLY SUPP_RGB444*/
  456. if (ret < 0)
  457. goto i2c_error_exit;
  458. ret = cbus_write_reg(sii9234, 0x86, 0x01);
  459. if (ret < 0)
  460. goto i2c_error_exit;
  461. ret = cbus_write_reg(sii9234, 0x87, 0);
  462. if (ret < 0)
  463. goto i2c_error_exit;
  464. ret = cbus_write_reg(sii9234, 0x88, (1<<7));
  465. if (ret < 0)
  466. goto i2c_error_exit;
  467. ret = cbus_write_reg(sii9234, 0x89, 0x0F);
  468. if (ret < 0)
  469. goto i2c_error_exit;
  470. ret = cbus_write_reg(sii9234, 0x8A, (1<<0) | (1<<1) | (1<<2));
  471. if (ret < 0)
  472. goto i2c_error_exit;
  473. ret = cbus_write_reg(sii9234, 0x8B, 0);
  474. if (ret < 0)
  475. goto i2c_error_exit;
  476. ret = cbus_write_reg(sii9234, 0x8C, 0);
  477. if (ret < 0)
  478. goto i2c_error_exit;
  479. ret = cbus_write_reg(sii9234, 0x8D, 16);
  480. if (ret < 0)
  481. goto i2c_error_exit;
  482. ret = cbus_write_reg(sii9234, 0x8E, 0x33);
  483. if (ret < 0)
  484. goto i2c_error_exit;
  485. ret = cbus_write_reg(sii9234, 0x8F, 0);
  486. if (ret < 0)
  487. goto i2c_error_exit;
  488. ret = cbus_read_reg(sii9234, 0x31, &value);
  489. if (ret < 0)
  490. goto i2c_error_exit;
  491. value |= 0x0C;
  492. ret = cbus_write_reg(sii9234, 0x31, value);
  493. if (ret < 0)
  494. goto i2c_error_exit;
  495. ret = cbus_write_reg(sii9234, 0x30, 0x01);
  496. if (ret < 0)
  497. goto i2c_error_exit;
  498. ret = cbus_read_reg(sii9234, 0x3C, &value);
  499. if (ret < 0)
  500. goto i2c_error_exit;
  501. value &= ~0x38;
  502. value |= 0x30;
  503. ret = cbus_write_reg(sii9234, 0x3C, value);
  504. if (ret < 0)
  505. goto i2c_error_exit;
  506. ret = cbus_read_reg(sii9234, 0x22, &value);
  507. if (ret < 0)
  508. goto i2c_error_exit;
  509. value &= ~0x0F;
  510. value |= 0x0D;
  511. ret = cbus_write_reg(sii9234, 0x22, value);
  512. if (ret < 0)
  513. goto i2c_error_exit;
  514. ret = cbus_read_reg(sii9234, 0x2E, &value);
  515. if (ret < 0)
  516. goto i2c_error_exit;
  517. value |= 0x15;
  518. ret = cbus_write_reg(sii9234, 0x2E, value);
  519. if (ret < 0)
  520. goto i2c_error_exit;
  521. ret = cbus_write_reg(sii9234, CBUS_INTR1_ENABLE_REG, 0);
  522. if (ret < 0)
  523. goto i2c_error_exit;
  524. ret = cbus_write_reg(sii9234, CBUS_INTR2_ENABLE_REG, 0);
  525. if (ret < 0)
  526. goto i2c_error_exit;
  527. return 0;
  528. i2c_error_exit:
  529. pr_err("[ERROR] %s()\n", __func__);
  530. return ret;
  531. }
  532. static void cbus_req_abort_error(struct sii9234_data *sii9234)
  533. {
  534. u8 abort_reason = 0;
  535. pr_debug("sii9234: MSC Request Aborted:");
  536. cbus_read_reg(sii9234, MSC_REQ_ABORT_REASON_REG, &abort_reason);
  537. if (abort_reason) {
  538. if (abort_reason & BIT_MSC_XFR_ABORT) {
  539. cbus_read_reg(sii9234, MSC_REQ_ABORT_REASON_REG,
  540. &abort_reason);
  541. pr_cont("ABORT_REASON_REG = %d\n", abort_reason);
  542. cbus_write_reg(sii9234, MSC_REQ_ABORT_REASON_REG, 0xff);
  543. }
  544. if (abort_reason & BIT_MSC_ABORT) {
  545. cbus_read_reg(sii9234, BIT_MSC_ABORT, &abort_reason);
  546. pr_cont("BIT_MSC_ABORT = %d\n", abort_reason);
  547. cbus_write_reg(sii9234, BIT_MSC_ABORT, 0xff);
  548. }
  549. if (abort_reason & ABORT_BY_PEER)
  550. pr_cont(" Peer Sent an ABORT");
  551. if (abort_reason & UNDEF_CMD)
  552. pr_cont(" Undefined Opcode");
  553. if (abort_reason & TIMEOUT)
  554. pr_cont(" Requestor Translation layer Timeout");
  555. if (abort_reason & PROTO_ERROR)
  556. pr_cont(" Protocol Error");
  557. if (abort_reason & MAX_FAIL) {
  558. u8 msc_retry_thr_val = 0;
  559. pr_cont(" Retry Threshold exceeded");
  560. cbus_read_reg(sii9234,
  561. MSC_RETRY_FAIL_LIM_REG,
  562. &msc_retry_thr_val);
  563. pr_cont("Retry Threshold value is:%d",
  564. msc_retry_thr_val);
  565. }
  566. }
  567. pr_cont("\n");
  568. }
  569. static void cbus_resp_abort_error(struct sii9234_data *sii9234)
  570. {
  571. u8 abort_reason = 0;
  572. pr_debug("sii9234: MSC Response Aborted:");
  573. cbus_read_reg(sii9234, MSC_RESP_ABORT_REASON_REG, &abort_reason);
  574. cbus_write_reg(sii9234, MSC_RESP_ABORT_REASON_REG, 0xff);
  575. if (abort_reason) {
  576. if (abort_reason & ABORT_BY_PEER)
  577. pr_cont(" Peer Sent an ABORT");
  578. if (abort_reason & UNDEF_CMD)
  579. pr_cont(" Undefined Opcode");
  580. if (abort_reason & TIMEOUT)
  581. pr_cont(" Requestor Translation layer Timeout");
  582. }
  583. pr_cont("\n");
  584. }
  585. static void force_usb_id_switch_open(struct sii9234_data *sii9234)
  586. {
  587. /*Disable CBUS discovery*/
  588. mhl_tx_clear_reg(sii9234, MHL_TX_DISC_CTRL1_REG, (1<<0));
  589. /*Force USB ID switch to open*/
  590. mhl_tx_set_reg(sii9234, MHL_TX_DISC_CTRL6_REG, USB_ID_OVR);
  591. mhl_tx_set_reg(sii9234, MHL_TX_DISC_CTRL3_REG, 0x86);
  592. /*Force upstream HPD to 0 when not in MHL mode.*/
  593. mhl_tx_clear_reg(sii9234, MHL_TX_INT_CTRL_REG, (1<<4) | (1<<5));
  594. }
  595. static void release_usb_id_switch_open(struct sii9234_data *sii9234)
  596. {
  597. msleep(T_SRC_CBUS_FLOAT);
  598. /* clear USB ID switch to open*/
  599. mhl_tx_clear_reg(sii9234, MHL_TX_DISC_CTRL6_REG, USB_ID_OVR);
  600. /* Enable CBUS discovery*/
  601. mhl_tx_set_reg(sii9234, MHL_TX_DISC_CTRL1_REG, (1<<0));
  602. }
  603. static bool cbus_ddc_abort_error(struct sii9234_data *sii9234)
  604. {
  605. u8 val1, val2;
  606. /* clear the ddc abort counter */
  607. cbus_write_reg(sii9234, 0x29, 0xFF);
  608. cbus_read_reg(sii9234, 0x29, &val1);
  609. usleep_range(3000, 4000);
  610. cbus_read_reg(sii9234, 0x29, &val2);
  611. if (val2 > (val1 + 50)) {
  612. pr_debug("Applying DDC Abort Safety(SWA 18958)\n)");
  613. mhl_tx_set_reg(sii9234, MHL_TX_SRST, (1<<3));
  614. mhl_tx_clear_reg(sii9234, MHL_TX_SRST, (1<<3));
  615. force_usb_id_switch_open(sii9234);
  616. release_usb_id_switch_open(sii9234);
  617. mhl_tx_write_reg(sii9234, MHL_TX_MHLTX_CTL1_REG, 0xD0);
  618. sii9234_tmds_control(sii9234, false);
  619. /* Disconnect and notify to OTG */
  620. return true;
  621. }
  622. pr_debug("sii9234: DDC abort interrupt\n");
  623. return false;
  624. }
  625. #ifdef CONFIG_SII9234_RCP
  626. static void rcp_uevent_report(struct sii9234_data *sii9234, u8 key)
  627. {
  628. if (!sii9234->input_dev) {
  629. pr_err("%s: sii9234->input_dev is NULL & skip rcp_report\n"
  630. , __func__);
  631. return;
  632. }
  633. pr_info("rcp_uevent_report key: %d\n", key);
  634. input_report_key(sii9234->input_dev, (unsigned int)key+1, 1);
  635. input_report_key(sii9234->input_dev, (unsigned int)key+1, 0);
  636. input_sync(sii9234->input_dev);
  637. }
  638. /*
  639. * is_rcp_code_valid: Validdates the recevied RCP key,
  640. * valid key is 1 to 1 map to fwk keylayer file sii9234_rcp.kl
  641. * located at (/system/usr/keylayout/sii9234_rcp.kl).
  642. *
  643. * New key support needs to be update is_rcp_key_code_valid at
  644. * driver side and /system/usr/keylayout/sii9234_rcp.kl at fwk side.
  645. */
  646. static int is_rcp_key_code_valid(u8 key)
  647. {
  648. switch (key+1) {
  649. /*should resemble /system/usr/keylayout/sii9234_rcp.kl*/
  650. case 1: /* ENTER WAKE_DROPPED*/
  651. case 2: /* DPAD_UP WAKE_DROPPED*/
  652. case 3: /* DPAD_DOWN WAKE_DROPPED*/
  653. case 4: /* DPAD_LEFT WAKE_DROPPED*/
  654. case 5: /* DPAD_RIGHT WAKE_DROPPED*/
  655. case 10: /* MENU WAKE_DROPPED*/
  656. case 14: /* BACK WAKE_DROPPED*/
  657. case 33: /* 0 */
  658. case 34: /* 1 */
  659. case 35: /* 2 */
  660. case 36: /* 3 */
  661. case 37: /* 4 */
  662. case 38: /* 5 */
  663. case 39: /* 6 */
  664. case 40: /* 7 */
  665. case 41: /* 8 */
  666. case 42: /* 9 */
  667. case 43: /* ENTER*/
  668. case 45: /* DEL */
  669. case 69: /* MEDIA_PLAY_PAUSE WAKE*/
  670. case 70: /* MEDIA_STOP WAKE*/
  671. case 71: /* MEDIA_PAUSE WAKE*/
  672. case 73: /* MEDIA_REWIND WAKE*/
  673. case 74: /* MEDIA_FAST_FORWARD WAKE*/
  674. case 76: /* MEDIA_NEXT WAKE*/
  675. case 77: /* MEDIA_PREVIOUS WAKE*/
  676. return 1;
  677. default:
  678. return 0;
  679. }
  680. }
  681. static void cbus_process_rcp_key(struct sii9234_data *sii9234, u8 key)
  682. {
  683. if (is_rcp_key_code_valid(key)) {
  684. /* Report the key */
  685. rcp_uevent_report(sii9234, key);
  686. /* Send the RCP ack */
  687. cbus_command_request(sii9234, CBUS_MSC_MSG,
  688. MSG_RCPK, key);
  689. } else {
  690. sii9234->error_key = key;
  691. /*
  692. * Send a RCPE(RCP Error Message) to Peer followed by
  693. * RCPK with old key-code so that initiator(TV) can
  694. * recognize failed key code.error code = 0x01 means
  695. * Ineffective key code was received.
  696. * See Table 21.(PRM)for details.
  697. */
  698. cbus_command_request(sii9234, CBUS_MSC_MSG, MSG_RCPE, 0x01);
  699. }
  700. }
  701. #endif
  702. static void cbus_process_rap_key(struct sii9234_data *sii9234, u8 key)
  703. {
  704. if (CBUS_MSC_RAP_CONTENT_ON == key)
  705. sii9234_tmds_control(sii9234, true);
  706. else if (CBUS_MSC_RAP_CONTENT_OFF == key)
  707. sii9234_tmds_control(sii9234, false);
  708. #ifndef CONFIG_MHL_NEW_CBUS_MSC_CMD
  709. cbus_command_request(sii9234, CBUS_MSC_MSG, MSG_RAPK, 0x00);
  710. #else
  711. sii9234_enqueue_msc_work(sii9234, CBUS_MSC_MSG, MSG_RAPK, 0x00, 0x0);
  712. #endif
  713. }
  714. /*
  715. * Incoming MSC_MSG : RCP/RAP/RCPK/RCPE/RAPK commands
  716. *
  717. * Process RCP key codes and the send supported keys to userspace.
  718. * If a key is not supported then an error ack is sent to the peer. Note
  719. * that by default all key codes are supported.
  720. *
  721. * An alternate method might be to decide the validity of the key in the
  722. * driver itself. However, the driver does not have any criteria to which
  723. * to make this decision.
  724. */
  725. static void cbus_handle_msc_msg(struct sii9234_data *sii9234)
  726. {
  727. u8 cmd_code, key;
  728. mutex_lock(&sii9234->cbus_lock);
  729. if (sii9234->state != STATE_ESTABLISHED) {
  730. pr_debug("sii9234: invalid MHL state\n");
  731. mutex_unlock(&sii9234->cbus_lock);
  732. return ;
  733. }
  734. cbus_read_reg(sii9234, CBUS_MSC_MSG_CMD_IN_REG, &cmd_code);
  735. cbus_read_reg(sii9234, CBUS_MSC_MSG_DATA_IN_REG, &key);
  736. pr_info("sii9234: cmd_code:%d, key:%d\n", cmd_code, key);
  737. switch (cmd_code) {
  738. case MSG_RCP:
  739. pr_debug("sii9234: RCP Arrived. KEY CODE:%d\n", key);
  740. mutex_unlock(&sii9234->cbus_lock);
  741. cbus_process_rcp_key(sii9234, key);
  742. return;
  743. case MSG_RAP:
  744. pr_debug("sii9234: RAP Arrived\n");
  745. mutex_unlock(&sii9234->cbus_lock);
  746. cbus_process_rap_key(sii9234, key);
  747. return;
  748. case MSG_RCPK:
  749. pr_debug("sii9234: RCPK Arrived\n");
  750. break;
  751. case MSG_RCPE:
  752. pr_debug("sii9234: RCPE Arrived\n");
  753. break;
  754. case MSG_RAPK:
  755. pr_debug("sii9234: RAPK Arrived\n");
  756. break;
  757. default:
  758. pr_debug("sii9234: MAC error\n");
  759. mutex_unlock(&sii9234->cbus_lock);
  760. #ifndef CONFIG_MHL_NEW_CBUS_MSC_CMD
  761. cbus_command_request(sii9234, CBUS_GET_MSC_ERR_CODE, 0, 0);
  762. #else
  763. sii9234_enqueue_msc_work(sii9234,
  764. CBUS_GET_MSC_ERR_CODE, 0, 0, 0x0);
  765. #endif
  766. return;
  767. }
  768. mutex_unlock(&sii9234->cbus_lock);
  769. }
  770. void mhl_path_enable(struct sii9234_data *sii9234, bool path_en)
  771. {
  772. pr_debug("sii9234: mhl_path_enable MHL_STATUS_PATH_ENABLED,");
  773. pr_debug(" path_en=%d !!!\n", path_en);
  774. if (path_en)
  775. sii9234->mhl_status_value.linkmode |= MHL_STATUS_PATH_ENABLED;
  776. else
  777. sii9234->mhl_status_value.linkmode &= ~MHL_STATUS_PATH_ENABLED;
  778. #ifndef CONFIG_MHL_NEW_CBUS_MSC_CMD
  779. cbus_command_request(sii9234, CBUS_WRITE_STAT,
  780. CBUS_LINK_CONTROL_2_REG, sii9234->mhl_status_value.linkmode);
  781. #else
  782. sii9234_enqueue_msc_work(sii9234, CBUS_WRITE_STAT,
  783. CBUS_LINK_CONTROL_2_REG,
  784. sii9234->mhl_status_value.linkmode, 0x0);
  785. #endif
  786. }
  787. #ifdef __SII9234_DEBUG__
  788. static void cbus_handle_wrt_burst_recd(struct sii9234_data *sii9234)
  789. {
  790. pr_debug("sii9234: CBUS WRT_BURST_RECD\n");
  791. }
  792. #endif
  793. static void cbus_handle_wrt_stat_recd(struct sii9234_data *sii9234)
  794. {
  795. u8 status_reg0, status_reg1;
  796. pr_debug("sii9234: CBUS WRT_STAT_RECD\n");
  797. /*
  798. * The two MHL status registers need to read to ensure that the MSC is
  799. * ready to receive the READ_DEVCAP command.
  800. * The READ_DEVCAP command is need to determine the dongle power state
  801. * and whether RCP, RCPE, RCPK, RAP, and RAPE are supported.
  802. *
  803. * Note that this is not documented properly in the PRM.
  804. */
  805. cbus_read_reg(sii9234, CBUS_MHL_STATUS_REG_0, &status_reg0);
  806. cbus_write_reg(sii9234, CBUS_MHL_STATUS_REG_0, 0xFF);
  807. cbus_read_reg(sii9234, CBUS_MHL_STATUS_REG_1, &status_reg1);
  808. cbus_write_reg(sii9234, CBUS_MHL_STATUS_REG_1, 0xFF);
  809. pr_debug("sii9234: STATUS_REG0 : [%d];STATUS_REG1 : [%d]\n",
  810. status_reg0, status_reg1);
  811. if (!(sii9234->mhl_status_value.linkmode & MHL_STATUS_PATH_ENABLED) &&
  812. (MHL_STATUS_PATH_ENABLED & status_reg1)) {
  813. mhl_path_enable(sii9234, true);
  814. } else if ((sii9234->mhl_status_value.linkmode
  815. & MHL_STATUS_PATH_ENABLED) &&
  816. !(MHL_STATUS_PATH_ENABLED & status_reg1)) {
  817. mhl_path_enable(sii9234, false);
  818. }
  819. if (status_reg0 & MHL_STATUS_DCAP_READY) {
  820. pr_debug("sii9234: DEV CAP READY\n");
  821. #ifndef CONFIG_MHL_NEW_CBUS_MSC_CMD
  822. cbus_command_request(sii9234, CBUS_READ_DEVCAP,
  823. DEVCAP_DEV_CAT, 0x00);
  824. cbus_command_request(sii9234, CBUS_READ_DEVCAP,
  825. DEVCAP_DEV_FEATURE_FLAG, 0x00);
  826. #else
  827. sii9234_enqueue_msc_work(sii9234, CBUS_READ_DEVCAP,
  828. DEVCAP_DEV_CAT, 0x00, 0x0);
  829. sii9234_enqueue_msc_work(sii9234, CBUS_READ_DEVCAP,
  830. DEVCAP_DEV_FEATURE_FLAG, 0x00, 0x0);
  831. sii9234_enqueue_msc_work(sii9234, CBUS_READ_DEVCAP,
  832. DEVCAP_DEVICE_ID_H, 0x0, 0x0);
  833. sii9234_enqueue_msc_work(sii9234, CBUS_READ_DEVCAP,
  834. DEVCAP_DEVICE_ID_L, 0x0, 0x0);
  835. sii9234_enqueue_msc_work(sii9234, CBUS_READ_DEVCAP,
  836. DEVCAP_RESERVED, 0x0, 0x0);
  837. #endif
  838. }
  839. }
  840. static void cbus_handle_set_int_recd(struct sii9234_data *sii9234)
  841. {
  842. u8 intr_reg0, intr_reg1, value;
  843. /* read and clear interrupt*/
  844. cbus_read_reg(sii9234, CBUS_MHL_INTR_REG_0, &intr_reg0);
  845. cbus_write_reg(sii9234, CBUS_MHL_INTR_REG_0, intr_reg0);
  846. cbus_read_reg(sii9234, CBUS_MHL_INTR_REG_1, &intr_reg1);
  847. cbus_write_reg(sii9234, CBUS_MHL_INTR_REG_1, intr_reg1);
  848. pr_debug("sii9234: INTR_REG0 : [%d]; INTR_REG1 : [%d]\n",
  849. intr_reg0, intr_reg1);
  850. if (intr_reg0 & MHL_INT_DCAP_CHG) {
  851. #ifndef CONFIG_MHL_NEW_CBUS_MSC_CMD
  852. pr_debug("sii9234: MHL_INT_DCAP_CHG\n");
  853. cbus_command_request(sii9234, CBUS_READ_DEVCAP,
  854. DEVCAP_DEV_CAT, 0x00);
  855. cbus_command_request(sii9234, CBUS_READ_DEVCAP,
  856. DEVCAP_DEV_FEATURE_FLAG, 0x00);
  857. #endif
  858. }
  859. if (intr_reg0 & MHL_INT_DSCR_CHG)
  860. pr_debug("sii9234: MHL_INT_DSCR_CHG\n");
  861. if (intr_reg0 & MHL_INT_REQ_WRT) {
  862. pr_debug("sii9234: MHL_INT_REQ_WRT\n");
  863. #ifndef CONFIG_MHL_NEW_CBUS_MSC_CMD
  864. cbus_command_request(sii9234, CBUS_SET_INT,
  865. MHL_RCHANGE_INT, MHL_INT_GRT_WRT);
  866. #else
  867. sii9234_enqueue_msc_work(sii9234, CBUS_SET_INT,
  868. MHL_RCHANGE_INT, MHL_INT_GRT_WRT, 0x0);
  869. #endif
  870. }
  871. if (intr_reg0 & MHL_INT_GRT_WRT)
  872. pr_debug("sii9234: MHL_INT_GRT_WRT\n");
  873. if (intr_reg1 & MHL_INT_EDID_CHG) {
  874. /* Enable Overriding HPD OUT */
  875. mhl_tx_set_reg(sii9234, MHL_TX_INT_CTRL_REG, (1<<4));
  876. /*
  877. * As per HDMI specification to indicate EDID change
  878. * in TV (or sink), we need to toggle HPD line.
  879. */
  880. /* HPD OUT = Low */
  881. mhl_tx_clear_reg(sii9234, MHL_TX_INT_CTRL_REG, (1<<5));
  882. /* A SET_HPD command shall not follow a CLR_HPD command
  883. * within less than THPD_WIDTH(50ms).
  884. */
  885. msleep(T_HPD_WIDTH);
  886. /* HPD OUT = High */
  887. mhl_tx_set_reg(sii9234, MHL_TX_INT_CTRL_REG, (1<<5));
  888. /* Disable Overriding of HPD OUT */
  889. mhl_tx_clear_reg(sii9234, MHL_TX_INT_CTRL_REG, (1<<4));
  890. }
  891. /* clear SET_INT_RECD interrupt */
  892. cbus_read_reg(sii9234, CBUS_MHL_INTR_REG_2, &value);
  893. cbus_write_reg(sii9234, CBUS_MHL_INTR_REG_2, value);
  894. cbus_read_reg(sii9234, CBUS_MHL_INTR_REG_3, &value);
  895. cbus_write_reg(sii9234, CBUS_MHL_INTR_REG_3, value);
  896. }
  897. static int sii9234_power_init(struct sii9234_data *sii9234)
  898. {
  899. int ret;
  900. /* Force the SiI9234 into the D0 state. */
  901. ret = tpi_write_reg(sii9234, TPI_DPD_REG, 0x3F);
  902. if (ret < 0)
  903. return ret;
  904. /* Enable TxPLL Clock */
  905. ret = hdmi_rx_write_reg(sii9234, HDMI_RX_TMDS_CLK_EN_REG, 0x01);
  906. if (ret < 0)
  907. return ret;
  908. /* Enable Tx Clock Path & Equalizer*/
  909. ret = hdmi_rx_write_reg(sii9234, HDMI_RX_TMDS_CH_EN_REG, 0x15);
  910. if (ret < 0)
  911. return ret;
  912. /* Power Up TMDS*/
  913. ret = mhl_tx_write_reg(sii9234, 0x08, 0x35);
  914. if (ret < 0)
  915. return ret;
  916. return ret;
  917. }
  918. static int sii9234_hdmi_init(struct sii9234_data *sii9234)
  919. {
  920. int ret = 0;
  921. /* Analog PLL Control
  922. * bits 5:4 = 2b00 as per characterization team.
  923. */
  924. ret = hdmi_rx_write_reg(sii9234, HDMI_RX_TMDS0_CCTRL1_REG, 0xC1);
  925. if (ret < 0)
  926. goto i2c_error_exit;
  927. /* PLL Calrefsel */
  928. ret = hdmi_rx_write_reg(sii9234, HDMI_RX_PLL_CALREFSEL_REG, 0x03);
  929. if (ret < 0)
  930. goto i2c_error_exit;
  931. /* VCO Cal */
  932. ret = hdmi_rx_write_reg(sii9234, HDMI_RX_PLL_VCOCAL_REG, 0x20);
  933. if (ret < 0)
  934. goto i2c_error_exit;
  935. /* Auto EQ */
  936. ret = hdmi_rx_write_reg(sii9234, HDMI_RX_EQ_DATA0_REG, 0x8A);
  937. if (ret < 0)
  938. goto i2c_error_exit;
  939. /* Auto EQ */
  940. ret = hdmi_rx_write_reg(sii9234, HDMI_RX_EQ_DATA1_REG, 0x6A);
  941. if (ret < 0)
  942. goto i2c_error_exit;
  943. /* Auto EQ */
  944. ret = hdmi_rx_write_reg(sii9234, HDMI_RX_EQ_DATA2_REG, 0xAA);
  945. if (ret < 0)
  946. goto i2c_error_exit;
  947. /* Auto EQ */
  948. ret = hdmi_rx_write_reg(sii9234, HDMI_RX_EQ_DATA3_REG, 0xCA);
  949. if (ret < 0)
  950. goto i2c_error_exit;
  951. /* Auto EQ */
  952. ret = hdmi_rx_write_reg(sii9234, HDMI_RX_EQ_DATA4_REG, 0xEA);
  953. if (ret < 0)
  954. goto i2c_error_exit;
  955. /* Manual zone */
  956. ret = hdmi_rx_write_reg(sii9234, HDMI_RX_TMDS_ZONE_CTRL_REG, 0xA0);
  957. if (ret < 0)
  958. goto i2c_error_exit;
  959. /* PLL Mode Value */
  960. ret = hdmi_rx_write_reg(sii9234, HDMI_RX_TMDS_MODE_CTRL_REG, 0x00);
  961. if (ret < 0)
  962. goto i2c_error_exit;
  963. ret = mhl_tx_write_reg(sii9234, MHL_TX_TMDS_CCTRL, 0x34);
  964. if (ret < 0)
  965. goto i2c_error_exit;
  966. ret = hdmi_rx_write_reg(sii9234, 0x45, 0x44);
  967. if (ret < 0)
  968. goto i2c_error_exit;
  969. /* Rx PLL BW ~ 4MHz */
  970. ret = hdmi_rx_write_reg(sii9234, 0x31, 0x0A);
  971. if (ret < 0)
  972. goto i2c_error_exit;
  973. /* Analog PLL Control
  974. * bits 5:4 = 2b00 as per characterization team.
  975. */
  976. ret = hdmi_rx_write_reg(sii9234, HDMI_RX_TMDS0_CCTRL1_REG, 0xC1);
  977. if (ret < 0)
  978. goto i2c_error_exit;
  979. return ret;
  980. i2c_error_exit:
  981. pr_err("[ERROR] %s()\n", __func__);
  982. return ret;
  983. }
  984. static int sii9234_mhl_tx_ctl_int(struct sii9234_data *sii9234)
  985. {
  986. int ret = 0;
  987. ret = mhl_tx_write_reg(sii9234, MHL_TX_MHLTX_CTL1_REG, 0xD0);
  988. if (ret < 0)
  989. goto i2c_error_exit;
  990. #ifdef __CONFIG_RSEN_LOST_PATCH__
  991. ret = mhl_tx_write_reg(sii9234, MHL_TX_MHLTX_CTL2_REG, 0xC0);
  992. if (ret < 0)
  993. goto i2c_error_exit;
  994. #else
  995. ret = mhl_tx_write_reg(sii9234, MHL_TX_MHLTX_CTL2_REG, 0xFC);
  996. if (ret < 0)
  997. goto i2c_error_exit;
  998. #endif
  999. ret = mhl_tx_write_reg(sii9234, MHL_TX_MHLTX_CTL4_REG,
  1000. sii9234->pdata->swing_level);
  1001. if (ret < 0)
  1002. goto i2c_error_exit;
  1003. ret = mhl_tx_write_reg(sii9234, MHL_TX_MHLTX_CTL7_REG, 0x0C);
  1004. if (ret < 0)
  1005. goto i2c_error_exit;
  1006. return ret;
  1007. i2c_error_exit:
  1008. pr_err("[ERROR] %s()\n", __func__);
  1009. return ret;
  1010. }
  1011. static void sii9234_power_down(struct sii9234_data *sii9234)
  1012. {
  1013. sii9234_disable_irq();
  1014. if (sii9234->claimed) {
  1015. if (sii9234->pdata->vbus_present)
  1016. #ifdef CONFIG_MHL_NEW_CBUS_MSC_CMD
  1017. sii9234->pdata->vbus_present(false , 0);
  1018. #else
  1019. sii9234->pdata->vbus_present(false);
  1020. #endif
  1021. }
  1022. sii9234->state = STATE_DISCONNECTED;
  1023. sii9234->claimed = false;
  1024. tpi_write_reg(sii9234, TPI_DPD_REG, 0);
  1025. /*turn on&off hpd festure for only QCT HDMI*/
  1026. mhl_hpd_handler(false);
  1027. }
  1028. int rsen_state_timer_out(struct sii9234_data *sii9234)
  1029. {
  1030. int ret = 0;
  1031. u8 value;
  1032. ret = mhl_tx_read_reg(sii9234, MHL_TX_SYSSTAT_REG, &value);
  1033. if (ret < 0)
  1034. goto err_exit;
  1035. sii9234->rsen = value & RSEN_STATUS;
  1036. if (value & RSEN_STATUS) {
  1037. pr_info("sii9234: MHL cable connected.. RESN High\n");
  1038. } else {
  1039. pr_info("sii9234: RSEN lost\n");
  1040. msleep(T_SRC_RXSENSE_DEGLITCH);
  1041. ret = mhl_tx_read_reg(sii9234, MHL_TX_SYSSTAT_REG, &value);
  1042. if (ret < 0)
  1043. goto err_exit;
  1044. pr_info("sys_stat: %x ~\n", value);
  1045. if ((value & RSEN_STATUS) == 0) {
  1046. pr_info("RSEN Really LOW ~\n");
  1047. /*To meet CTS 3.3.22.2 spec*/
  1048. sii9234_tmds_control(sii9234, false);
  1049. force_usb_id_switch_open(sii9234);
  1050. release_usb_id_switch_open(sii9234);
  1051. ret = -1;
  1052. goto err_exit;
  1053. } else
  1054. pr_info("sii9234: RSEN recovery\n");
  1055. }
  1056. return ret;
  1057. err_exit:
  1058. /*turn off mhl and change usb_sel to usb*/
  1059. #ifdef CONFIG_MHL_D3_SUPPORT
  1060. goto_d3(NULL);
  1061. #else
  1062. mhl_onoff_ex(0);
  1063. #endif
  1064. return ret;
  1065. }
  1066. #ifdef CONFIG_MHL_D3_SUPPORT
  1067. static void goto_d3(struct work_struct *work)
  1068. {
  1069. struct sii9234_data *sii9234 = dev_get_drvdata(sii9244_mhldev);
  1070. int ret;
  1071. u8 value;
  1072. pr_info("sii9234: detection started d3\n");
  1073. sii9234_callback_sched = 0;
  1074. sii9234->mhl_status_value.linkmode = MHL_STATUS_CLK_MODE_NORMAL;
  1075. sii9234->rgnd = RGND_UNKNOWN;
  1076. sii9234->state = STATE_DISCONNECTED;
  1077. sii9234->rsen = false;
  1078. memset(cbus_pkt_buf, 0x00, sizeof(cbus_pkt_buf));
  1079. ret = sii9234_power_init(sii9234);
  1080. if (ret < 0)
  1081. goto unhandled;
  1082. ret = sii9234_hdmi_init(sii9234);
  1083. if (ret < 0)
  1084. goto unhandled;
  1085. ret = sii9234_mhl_tx_ctl_int(sii9234);
  1086. if (ret < 0)
  1087. goto unhandled;
  1088. /* Enable HDCP Compliance safety*/
  1089. ret = mhl_tx_write_reg(sii9234, 0x2B, 0x01);
  1090. if (ret < 0)
  1091. goto unhandled;
  1092. /* CBUS discovery cycle time for each drive and float = 150us*/
  1093. ret = mhl_tx_read_reg(sii9234, MHL_TX_DISC_CTRL1_REG, &value);
  1094. if (ret < 0)
  1095. goto unhandled;
  1096. value &= ~(1<<3);
  1097. value |= (1<<2);
  1098. ret = mhl_tx_write_reg(sii9234, MHL_TX_DISC_CTRL1_REG, value);
  1099. if (ret < 0)
  1100. goto unhandled;
  1101. /* Clear bit 6 (reg_skip_rgnd) */
  1102. ret = mhl_tx_write_reg(sii9234, MHL_TX_DISC_CTRL2_REG,
  1103. (1<<7) /* Reserved Bit */ |
  1104. 2 << ATT_THRESH_SHIFT | DEGLITCH_TIME_50MS);
  1105. if (ret < 0)
  1106. goto unhandled;
  1107. /* Changed from 66 to 65 for 94[1:0] = 01 = 5k reg_cbusmhl_pup_sel */
  1108. /* 1.8V CBUS VTH & GND threshold */
  1109. /*To meet CTS 3.3.7.2 spec*/
  1110. ret = mhl_tx_write_reg(sii9234, MHL_TX_DISC_CTRL5_REG, 0x77);
  1111. if (ret < 0)
  1112. goto unhandled;
  1113. /* set bit 2 and 3, which is Initiator Timeout */
  1114. ret = cbus_read_reg(sii9234, CBUS_LINK_CONTROL_2_REG, &value);
  1115. if (ret < 0)
  1116. goto unhandled;
  1117. value |= 0x0C;
  1118. ret = cbus_write_reg(sii9234, CBUS_LINK_CONTROL_2_REG, value);
  1119. if (ret < 0)
  1120. goto unhandled;
  1121. ret = mhl_tx_write_reg(sii9234, MHL_TX_MHLTX_CTL6_REG, 0xA0);
  1122. if (ret < 0)
  1123. goto unhandled;
  1124. /* RGND & single discovery attempt (RGND blocking) */
  1125. ret = mhl_tx_write_reg(sii9234, MHL_TX_DISC_CTRL6_REG, BLOCK_RGND_INT |
  1126. DVRFLT_SEL | SINGLE_ATT);
  1127. if (ret < 0)
  1128. goto unhandled;
  1129. /* Use VBUS path of discovery state machine*/
  1130. ret = mhl_tx_write_reg(sii9234, MHL_TX_DISC_CTRL8_REG, 0);
  1131. if (ret < 0)
  1132. goto unhandled;
  1133. ret = mhl_tx_set_reg(sii9234, MHL_TX_DISC_CTRL6_REG, USB_ID_OVR);
  1134. if (ret < 0)
  1135. goto unhandled;
  1136. /* To allow RGND engine to operate correctly.
  1137. * When moving the chip from D2 to D0 (power up, init regs)
  1138. * the values should be
  1139. * 94[1:0] = 01 reg_cbusmhl_pup_sel[1:0] should be set for 5k
  1140. * 93[7:6] = 10 reg_cbusdisc_pup_sel[1:0] should be
  1141. * set for 10k (default)
  1142. * 93[5:4] = 00 reg_cbusidle_pup_sel[1:0] = open (default)
  1143. */
  1144. ret = mhl_tx_set_reg(sii9234, MHL_TX_DISC_CTRL3_REG, 0xA6);
  1145. if (ret < 0)
  1146. goto unhandled;
  1147. /* change from CC to 8C to match 5K*/
  1148. /*To meet CTS 3.3.72 spec*/
  1149. ret = mhl_tx_set_reg(sii9234, MHL_TX_DISC_CTRL4_REG, 0x8C);
  1150. if (ret < 0)
  1151. goto unhandled;
  1152. /* Configure the interrupt as active high */
  1153. ret = mhl_tx_clear_reg(sii9234, MHL_TX_INT_CTRL_REG, (1<<2) | (1<<1));
  1154. if (ret < 0)
  1155. goto unhandled;
  1156. msleep(25);
  1157. /* release usb_id switch */
  1158. ret = mhl_tx_clear_reg(sii9234, MHL_TX_DISC_CTRL6_REG, USB_ID_OVR);
  1159. if (ret < 0)
  1160. goto unhandled;
  1161. ret = mhl_tx_write_reg(sii9234, MHL_TX_DISC_CTRL1_REG, 0x27);
  1162. if (ret < 0)
  1163. goto unhandled;
  1164. ret = sii9234_cbus_reset(sii9234);
  1165. if (ret < 0)
  1166. goto unhandled;
  1167. ret = sii9234_cbus_init(sii9234);
  1168. if (ret < 0)
  1169. goto unhandled;
  1170. /* Enable Auto soft reset on SCDT = 0*/
  1171. ret = mhl_tx_write_reg(sii9234, 0x05, 0x04);
  1172. if (ret < 0)
  1173. goto unhandled;
  1174. /* HDMI Transcode mode enable*/
  1175. ret = mhl_tx_write_reg(sii9234, 0x0D, 0x1C);
  1176. if (ret < 0)
  1177. goto unhandled;
  1178. ret = mhl_tx_write_reg(sii9234, MHL_TX_INTR4_ENABLE_REG,
  1179. RGND_READY_MASK | CBUS_LKOUT_MASK |
  1180. MHL_DISC_FAIL_MASK | MHL_EST_MASK);
  1181. if (ret < 0)
  1182. goto unhandled;
  1183. ret = mhl_tx_write_reg(sii9234, MHL_TX_INTR1_ENABLE_REG,
  1184. (1<<5) | (1<<6));
  1185. if (ret < 0)
  1186. goto unhandled;
  1187. /* this point is very importand before megsure RGND impedance*/
  1188. force_usb_id_switch_open(sii9234);
  1189. ret = mhl_tx_clear_reg(sii9234, MHL_TX_DISC_CTRL4_REG,
  1190. (1<<7) | (1<<6) | (1<<5) | (1<<4));
  1191. if (ret < 0)
  1192. goto unhandled;
  1193. ret = mhl_tx_clear_reg(sii9234, MHL_TX_DISC_CTRL5_REG, (1<<1) | (1<<0));
  1194. if (ret < 0)
  1195. goto unhandled;
  1196. release_usb_id_switch_open(sii9234);
  1197. /*end of this*/
  1198. /* Force upstream HPD to 0 when not in MHL mode */
  1199. ret = mhl_tx_clear_reg(sii9234, MHL_TX_INT_CTRL_REG, (1<<5));
  1200. if (ret < 0)
  1201. goto unhandled;
  1202. ret = mhl_tx_set_reg(sii9234, MHL_TX_INT_CTRL_REG, (1<<4));
  1203. if (ret < 0)
  1204. goto unhandled;
  1205. ret = hdmi_rx_write_reg(sii9234, 0x01, 0x03);
  1206. if (ret < 0)
  1207. goto unhandled;
  1208. ret = tpi_read_reg(sii9234, 0x3D, &value);
  1209. if (ret < 0)
  1210. goto unhandled;
  1211. value &= ~BIT0;
  1212. ret = tpi_write_reg(sii9234, 0x3D, value);
  1213. if (ret < 0)
  1214. goto unhandled;
  1215. pr_info("sii9234 : go_to d3 mode!!!\n");
  1216. if (sii9234_callback_sched == 1)
  1217. pr_info("debug_message\n");
  1218. else
  1219. sii9234_enable_irq();
  1220. unhandled:
  1221. if (detached_status == 1)
  1222. pr_info("already mhl_state off\n");
  1223. }
  1224. #endif
  1225. #ifdef CONFIG_MHL_NEW_CBUS_MSC_CMD
  1226. void sii9234_process_msc_work(struct work_struct *work)
  1227. {
  1228. u8 value;
  1229. int ret;
  1230. struct msc_packet *p_msc_pkt, *scratch;
  1231. struct sii9234_data *sii9234 = container_of(work,
  1232. struct sii9234_data,
  1233. msc_work);
  1234. /*Do not process msc untill STATE_ESTABLISHED*/
  1235. if (sii9234->state != STATE_ESTABLISHED)
  1236. return;
  1237. mutex_lock(&sii9234->cbus_lock);
  1238. mutex_lock(&sii9234->lock);
  1239. pr_debug("%s() - start\n", __func__);
  1240. list_for_each_entry_safe(p_msc_pkt, scratch,
  1241. &g_msc_packet_list, p_msc_packet_list) {
  1242. pr_debug("[MSC] %s() command(0x%x), offset(0x%x), data_1(0x%x), data_2(0x%x)\n",
  1243. __func__, p_msc_pkt->command, p_msc_pkt->offset,
  1244. p_msc_pkt->data_1, p_msc_pkt->data_2);
  1245. /* msc request */
  1246. ret = sii9234_msc_req_locked(sii9234, p_msc_pkt);
  1247. if (ret < 0) {
  1248. pr_info("%s(): msc_req_locked error %d\n",
  1249. __func__, ret);
  1250. goto exit;
  1251. }
  1252. /* MSC_REQ_DONE received */
  1253. switch (p_msc_pkt->command) {
  1254. case CBUS_MSC_MSG:
  1255. if ((p_msc_pkt->offset == MSG_RCPE) &&
  1256. (p_msc_pkt->data_2 == 0x01)) {
  1257. sii9234_enqueue_msc_work(
  1258. sii9234, CBUS_MSC_MSG,
  1259. MSG_RCPK, MSG_RCPK,
  1260. 0x0);
  1261. }
  1262. break;
  1263. case CBUS_WRITE_STAT:
  1264. break;
  1265. case CBUS_SET_INT:
  1266. if ((p_msc_pkt->offset == MHL_RCHANGE_INT) &&
  1267. (p_msc_pkt->data_1 == MHL_INT_DSCR_CHG)) {
  1268. /*
  1269. *Write burst final step
  1270. *Req->GRT->Write->DSCR
  1271. */
  1272. pr_debug("sii9234: MHL_RCHANGE_INT & MHL_INT_DSCR_CHG\n");
  1273. } else if ((p_msc_pkt->offset == MHL_RCHANGE_INT) &&
  1274. (p_msc_pkt->data_1 == MHL_INT_DCAP_CHG)) {
  1275. pr_debug("sii9234: MHL_RCHANGE_INT & MHL_INT_DCAP_CHG\n");
  1276. sii9234->cbus_pkt.command = CBUS_IDLE;
  1277. sii9234_enqueue_msc_work(sii9234,
  1278. CBUS_WRITE_STAT,
  1279. MHL_STATUS_REG_CONNECTED_RDY,
  1280. MHL_STATUS_DCAP_READY, 0x0);
  1281. }
  1282. break;
  1283. case CBUS_WRITE_BURST:
  1284. sii9234_enqueue_msc_work(sii9234, CBUS_SET_INT,
  1285. MHL_RCHANGE_INT,
  1286. MHL_INT_DSCR_CHG, 0x0);
  1287. break;
  1288. case CBUS_READ_DEVCAP:
  1289. ret = cbus_read_reg(sii9234,
  1290. CBUS_MSC_FIRST_DATA_IN_REG, &value);
  1291. if (ret < 0)
  1292. break;
  1293. switch (p_msc_pkt->offset) {
  1294. case DEVCAP_DEV_STATE:
  1295. pr_debug("sii9234: DEVCAP_DEV_STATE\n");
  1296. break;
  1297. case DEVCAP_MHL_VERSION:
  1298. sii9234->devcap.mhl_ver = value;
  1299. pr_debug("sii9234: MHL_VERSION: %X\n", value);
  1300. break;
  1301. case DEVCAP_DEV_CAT:
  1302. if (value & MHL_DEV_CATEGORY_POW_BIT)
  1303. pr_debug("sii9234: CAT=POWERED");
  1304. else
  1305. pr_debug("sii9234: CAT=UNPOWERED");
  1306. break;
  1307. case DEVCAP_ADOPTER_ID_H:
  1308. sii9234->devcap.adopter_id =
  1309. (value & 0xFF) << 0x8;
  1310. pr_debug("sii9234: DEVCAP_ADOPTER_ID_H = %X\n",
  1311. value);
  1312. break;
  1313. case DEVCAP_ADOPTER_ID_L:
  1314. sii9234->devcap.adopter_id |= value & 0xFF;
  1315. pr_debug("sii9234: DEVCAP_ADOPTER_ID_L = %X\n",
  1316. value);
  1317. break;
  1318. case DEVCAP_VID_LINK_MODE:
  1319. sii9234->devcap.vid_link_mode = 0x3F & value;
  1320. pr_debug("sii9234: MHL_CAP_VID_LINK_MODE = %d\n",
  1321. sii9234->devcap.vid_link_mode);
  1322. break;
  1323. case DEVCAP_AUD_LINK_MODE:
  1324. sii9234->devcap.aud_link_mode = 0x03 & value;
  1325. pr_debug("sii9234: DEVCAP_AUD_LINK_MODE =%d\n",
  1326. sii9234->devcap.aud_link_mode);
  1327. break;
  1328. case DEVCAP_VIDEO_TYPE:
  1329. sii9234->devcap.video_type = 0x8F & value;
  1330. pr_debug("sii9234: DEVCAP_VIDEO_TYPE =%d\n",
  1331. sii9234->devcap.video_type);
  1332. break;
  1333. case DEVCAP_LOG_DEV_MAP:
  1334. sii9234->devcap.log_dev_map = value;
  1335. pr_debug("sii9234: DEVCAP_LOG_DEV_MAP =%d\n",
  1336. sii9234->devcap.log_dev_map);
  1337. break;
  1338. case DEVCAP_BANDWIDTH:
  1339. sii9234->devcap.bandwidth = value;
  1340. pr_debug("sii9234: DEVCAP_BANDWIDTH =%d\n",
  1341. sii9234->devcap.bandwidth);
  1342. break;
  1343. case DEVCAP_DEV_FEATURE_FLAG:
  1344. if ((value & MHL_FEATURE_RCP_SUPPORT) == 0)
  1345. pr_debug("sii9234: FEATURE_FLAG=RCP");
  1346. if ((value & MHL_FEATURE_RAP_SUPPORT) == 0)
  1347. pr_debug("sii9234: FEATURE_FLAG=RAP\n");
  1348. if ((value & MHL_FEATURE_SP_SUPPORT) == 0)
  1349. pr_debug("sii9234: FEATURE_FLAG=SP\n");
  1350. break;
  1351. case DEVCAP_DEVICE_ID_H:
  1352. sii9234->devcap.device_id =
  1353. (value & 0xFF) << 0x8;
  1354. pr_info("sii9234: DEVICE_ID_H=0x%x\n", value);
  1355. break;
  1356. case DEVCAP_DEVICE_ID_L:
  1357. sii9234->devcap.device_id |= value & 0xFF;
  1358. pr_info("sii9234: DEVICE_ID_L=0x%x\n", value);
  1359. break;
  1360. case DEVCAP_SCRATCHPAD_SIZE:
  1361. sii9234->devcap.scratchpad_size = value;
  1362. pr_debug("sii9234: DEVCAP_SCRATCHPAD_SIZE =%d\n",
  1363. sii9234->devcap.scratchpad_size);
  1364. break;
  1365. case DEVCAP_INT_STAT_SIZE:
  1366. sii9234->devcap.int_stat_size = value;
  1367. pr_debug("sii9234: DEVCAP_INT_STAT_SIZE =%d\n",
  1368. sii9234->devcap.int_stat_size);
  1369. break;
  1370. case DEVCAP_RESERVED:
  1371. sii9234->dcap_ready_status = 1;
  1372. sii9234->devcap.reserved_data = value;
  1373. pr_info("sii9234: DEVCAP_RESERVED : %d\n",
  1374. value);
  1375. wake_up(&sii9234->wq);
  1376. break;
  1377. default:
  1378. pr_debug("sii9234: DEVCAP DEFAULT\n");
  1379. break;
  1380. }
  1381. break;
  1382. default:
  1383. break;
  1384. }
  1385. list_del(&p_msc_pkt->p_msc_packet_list);
  1386. pr_debug("[MSC] %s() free item , addr = 0x%x, cnt=%d\n",
  1387. __func__, (unsigned int)p_msc_pkt, --g_list_cnt);
  1388. kfree(p_msc_pkt);
  1389. }
  1390. exit:
  1391. mutex_unlock(&sii9234->lock);
  1392. mutex_unlock(&sii9234->cbus_lock);
  1393. }
  1394. static int sii9234_enqueue_msc_work(struct sii9234_data *sii9234, u8 command,
  1395. u8 offset, u8 data_1, u8 data_2)
  1396. {
  1397. struct msc_packet *packet_item;
  1398. packet_item = kmalloc(sizeof(struct msc_packet), GFP_KERNEL);
  1399. if (!packet_item) {
  1400. pr_err("[ERROR] %s() kmalloc error\n", __func__);
  1401. return -ENOMEM;
  1402. } else
  1403. pr_debug("[MSC] %s() add item, addr = 0x%x, cnt=%d\n",
  1404. __func__, (unsigned int)packet_item, ++g_list_cnt);
  1405. packet_item->command = command;
  1406. packet_item->offset = offset;
  1407. packet_item->data_1 = data_1;
  1408. packet_item->data_2 = data_2;
  1409. pr_debug("[MSC] %s() command(0x%x), offset(0x%x), data_1(0x%x), data_2(0x%x)\n",
  1410. __func__, command, offset, data_1, data_2);
  1411. list_add_tail(&packet_item->p_msc_packet_list, &g_msc_packet_list);
  1412. pr_debug("[MSC] %s() msc work schedule\n", __func__);
  1413. queue_work(sii9234_msc_wq, &(sii9234->msc_work));
  1414. return 0;
  1415. }
  1416. /* Must call with sii9234->lock held */
  1417. static int sii9234_msc_req_locked(struct sii9234_data *sii9234,
  1418. struct msc_packet *msc_pkt)
  1419. {
  1420. int ret;
  1421. u8 start_command;
  1422. init_completion(&sii9234->msc_complete);
  1423. cbus_write_reg(sii9234, CBUS_MSC_OFFSET_REG, msc_pkt->offset);
  1424. if (msc_pkt->command == CBUS_MSC_MSG)
  1425. msc_pkt->data_1 = msc_pkt->offset;
  1426. cbus_write_reg(sii9234, CBUS_MSC_FIRST_DATA_OUT_REG, msc_pkt->data_1);
  1427. switch (msc_pkt->command) {
  1428. case CBUS_SET_INT:
  1429. case CBUS_WRITE_STAT:
  1430. start_command = START_BIT_WRITE_STAT_INT;
  1431. break;
  1432. case CBUS_MSC_MSG:
  1433. cbus_write_reg(sii9234, CBUS_MSC_SECOND_DATA_OUT_REG,
  1434. msc_pkt->data_2);
  1435. cbus_write_reg(sii9234, CBUS_MSC_OFFSET_REG, msc_pkt->command);
  1436. start_command = START_BIT_MSC_MSG;
  1437. break;
  1438. case CBUS_READ_DEVCAP:
  1439. start_command = START_BIT_READ_DEVCAP;
  1440. break;
  1441. case CBUS_WRITE_BURST:
  1442. start_command = START_BIT_WRITE_BURST;
  1443. break;
  1444. case CBUS_GET_STATE:
  1445. case CBUS_GET_VENDOR_ID:
  1446. case CBUS_SET_HPD:
  1447. case CBUS_CLR_HPD:
  1448. case CBUS_GET_MSC_ERR_CODE:
  1449. case CBUS_GET_SC3_ERR_CODE:
  1450. case CBUS_GET_SC1_ERR_CODE:
  1451. case CBUS_GET_DDC_ERR_CODE:
  1452. cbus_write_reg(sii9234, CBUS_MSC_OFFSET_REG, msc_pkt->command);
  1453. start_command = START_BIT_MSC_RESERVED;
  1454. break;
  1455. default:
  1456. pr_err("[ERROR] %s() invalid msc command(%d)\n",
  1457. __func__, msc_pkt->command);
  1458. return -EINVAL;
  1459. }
  1460. cbus_write_reg(sii9234, CBUS_MSC_COMMAND_START_REG, start_command);
  1461. mutex_unlock(&sii9234->lock);
  1462. ret = wait_for_completion_timeout(&sii9234->msc_complete,
  1463. msecs_to_jiffies(300));
  1464. if (ret == 0)
  1465. printk(KERN_ERR "[ERROR] %s() MSC_REQ_DONE timeout\n",
  1466. __func__);
  1467. mutex_lock(&sii9234->lock);
  1468. return ret ? 0 : -EIO;
  1469. }
  1470. #endif /* CONFIG_MHL_NEW_CBUS_MSC_CMD end */
  1471. static void mhl_cbus_write_stat_worker(struct work_struct *p)
  1472. {
  1473. struct sii9234_data *sii9234 = dev_get_drvdata(sii9244_mhldev);
  1474. #ifndef CONFIG_MHL_NEW_CBUS_MSC_CMD
  1475. cbus_command_request(sii9234, CBUS_WRITE_STAT, CBUS_LINK_CONTROL_2_REG,
  1476. sii9234->mhl_status_value.linkmode);
  1477. #else
  1478. sii9234_enqueue_msc_work(sii9234, CBUS_WRITE_STAT,
  1479. CBUS_LINK_CONTROL_2_REG,
  1480. sii9234->mhl_status_value.linkmode, 0x0);
  1481. #endif
  1482. return;
  1483. }
  1484. static void sii9234_detection_callback(struct work_struct *work)
  1485. {
  1486. struct sii9234_data *sii9234 = dev_get_drvdata(sii9244_mhldev);
  1487. int ret;
  1488. u8 value;
  1489. pr_debug("sii9234: detection started\n");
  1490. sii9234_mutex_lock(&sii9234->lock);
  1491. sii9234_callback_sched = 1;
  1492. sii9234->mhl_status_value.linkmode = MHL_STATUS_CLK_MODE_NORMAL;
  1493. sii9234->rgnd = RGND_UNKNOWN;
  1494. sii9234->state = STATE_DISCONNECTED;
  1495. sii9234->rsen = false;
  1496. sii9234->dcap_ready_status = 0;
  1497. memset(cbus_pkt_buf, 0x00, sizeof(cbus_pkt_buf));
  1498. ret = sii9234_power_init(sii9234);
  1499. if (ret < 0) {
  1500. pr_err("[ERROR] %s() - sii9234_power_init\n", __func__);
  1501. goto unhandled;
  1502. }
  1503. ret = sii9234_cbus_reset(sii9234);
  1504. if (ret < 0) {
  1505. pr_err("[ERROR] %s() - sii9234_cbus_reset\n", __func__);
  1506. goto unhandled;
  1507. }
  1508. ret = sii9234_hdmi_init(sii9234);
  1509. if (ret < 0) {
  1510. pr_err("[ERROR] %s() - sii9234_hdmi_init\n", __func__);
  1511. goto unhandled;
  1512. }
  1513. ret = sii9234_mhl_tx_ctl_int(sii9234);
  1514. if (ret < 0) {
  1515. pr_err("[ERROR] %s() - sii9234_mhl_tx_ctl_int\n", __func__);
  1516. goto unhandled;
  1517. }
  1518. /* Enable HDCP Compliance safety*/
  1519. ret = mhl_tx_write_reg(sii9234, 0x2B, 0x01);
  1520. if (ret < 0) {
  1521. pr_err("[ERROR] %s() - mhl_tx_write_reg 0x2B\n", __func__);
  1522. goto unhandled;
  1523. }
  1524. /* CBUS discovery cycle time for each drive and float = 150us*/
  1525. ret = mhl_tx_read_reg(sii9234, MHL_TX_DISC_CTRL1_REG, &value);
  1526. if (ret < 0) {
  1527. pr_err("[ERROR] %s() - MHL_TX_DISC_CTRL1_REG\n", __func__);
  1528. goto unhandled;
  1529. }
  1530. value &= ~(1<<3);
  1531. value |= (1<<2);
  1532. ret = mhl_tx_write_reg(sii9234, MHL_TX_DISC_CTRL1_REG, value);
  1533. if (ret < 0) {
  1534. pr_err("[ERROR] %s() - MHL_TX_DISC_CTRL1_REG\n", __func__);
  1535. goto unhandled;
  1536. }
  1537. /* Clear bit 6 (reg_skip_rgnd) */
  1538. ret = mhl_tx_write_reg(sii9234, MHL_TX_DISC_CTRL2_REG,
  1539. (1<<7) /* Reserved Bit */ |
  1540. 2 << ATT_THRESH_SHIFT |
  1541. DEGLITCH_TIME_50MS);
  1542. if (ret < 0) {
  1543. pr_err("[ERROR] %s() - Clear bit 6\n", __func__);
  1544. goto unhandled;
  1545. }
  1546. /* Changed from 66 to 65 for 94[1:0] = 01 = 5k reg_cbusmhl_pup_sel */
  1547. /* 1.8V CBUS VTH & GND threshold */
  1548. /*To meet CTS 3.3.7.2 spec*/
  1549. ret = mhl_tx_write_reg(sii9234, MHL_TX_DISC_CTRL5_REG, 0x77);
  1550. if (ret < 0) {
  1551. pr_err("[ERROR] %s() - MHL_TX_DISC_CTRL5_REG\n", __func__);
  1552. goto unhandled;
  1553. }
  1554. /* set bit 2 and 3, which is Initiator Timeout */
  1555. ret = cbus_read_reg(sii9234, CBUS_LINK_CONTROL_2_REG, &value);
  1556. if (ret < 0) {
  1557. pr_err("[ERROR] %s()-read CBUS_LINK_CONTROL_2_REG\n", __func__);
  1558. goto unhandled;
  1559. }
  1560. value |= 0x0C;
  1561. ret = cbus_write_reg(sii9234, CBUS_LINK_CONTROL_2_REG, value);
  1562. if (ret < 0) {
  1563. pr_err("[ERROR]%s()-write CBUS_LINK_CONTROL_2_REG\n", __func__);
  1564. goto unhandled;
  1565. }
  1566. ret = mhl_tx_write_reg(sii9234, MHL_TX_MHLTX_CTL6_REG, 0xA0);
  1567. if (ret < 0) {
  1568. pr_err("[ERROR] %s() -write MHL_TX_MHLTX_CTL6_REG\n", __func__);
  1569. goto unhandled;
  1570. }
  1571. /* RGND & single discovery attempt (RGND blocking) */
  1572. ret = mhl_tx_write_reg(sii9234, MHL_TX_DISC_CTRL6_REG, BLOCK_RGND_INT |
  1573. DVRFLT_SEL | SINGLE_ATT);
  1574. if (ret < 0) {
  1575. pr_err("[ERROR] %s()-write MHL_TX_DISC_CTRL6_REG\n", __func__);
  1576. goto unhandled;
  1577. }
  1578. /* Use VBUS path of discovery state machine*/
  1579. ret = mhl_tx_write_reg(sii9234, MHL_TX_DISC_CTRL8_REG, 0);
  1580. if (ret < 0) {
  1581. pr_err("[ERROR] %s()-write MHL_TX_DISC_CTRL8_REG\n", __func__);
  1582. goto unhandled;
  1583. }
  1584. ret = mhl_tx_set_reg(sii9234, MHL_TX_DISC_CTRL6_REG, USB_ID_OVR);
  1585. if (ret < 0) {
  1586. pr_err("[ERROR] %s() - set MHL_TX_DISC_CTRL6_REG\n", __func__);
  1587. goto unhandled;
  1588. }
  1589. /* To allow RGND engine to operate correctly.
  1590. * When moving the chip from D2 to D0 (power up, init regs)
  1591. * the values should be
  1592. * 94[1:0] = 01 reg_cbusmhl_pup_sel[1:0] should be set for 5k
  1593. * 93[7:6] = 10 reg_cbusdisc_pup_sel[1:0] should be
  1594. * set for 10k (default)
  1595. * 93[5:4] = 00 reg_cbusidle_pup_sel[1:0] = open (default)
  1596. */
  1597. ret = mhl_tx_set_reg(sii9234, MHL_TX_DISC_CTRL3_REG, 0x86);
  1598. if (ret < 0) {
  1599. pr_err("[ERROR] %s() - set MHL_TX_DISC_CTRL3_REG\n", __func__);
  1600. goto unhandled;
  1601. }
  1602. /* change from CC to 8C to match 5K*/
  1603. /*To meet CTS 3.3.72 spec*/
  1604. ret = mhl_tx_set_reg(sii9234, MHL_TX_DISC_CTRL4_REG, 0x8C);
  1605. if (ret < 0) {
  1606. pr_err("[ERROR] %s() - set MHL_TX_DISC_CTRL4_REG\n", __func__);
  1607. goto unhandled;
  1608. }
  1609. /* Force upstream HPD to 0 when not in MHL mode */
  1610. ret = mhl_tx_clear_reg(sii9234, MHL_TX_INT_CTRL_REG, (1<<5));
  1611. if (ret < 0) {
  1612. pr_err("[ERROR] %s() - clear MHL_TX_INT_CTRL_REG\n", __func__);
  1613. goto unhandled;
  1614. }
  1615. ret = mhl_tx_set_reg(sii9234, MHL_TX_INT_CTRL_REG, (1<<4));
  1616. if (ret < 0) {
  1617. pr_err("[ERROR] %s() - set MHL_TX_INT_CTRL_REG\n", __func__);
  1618. goto unhandled;
  1619. }
  1620. /* Configure the interrupt as active high */
  1621. ret = mhl_tx_clear_reg(sii9234, MHL_TX_INT_CTRL_REG, (1<<2) | (1<<1));
  1622. if (ret < 0) {
  1623. pr_err("[ERROR] %s() - clear MHL_TX_INT_CTRL_REG\n", __func__);
  1624. goto unhandled;
  1625. }
  1626. msleep(25);
  1627. /* release usb_id switch */
  1628. ret = mhl_tx_clear_reg(sii9234, MHL_TX_DISC_CTRL6_REG, USB_ID_OVR);
  1629. if (ret < 0) {
  1630. pr_err("[ERROR] %s() - clear MHL_TX_DISC_CTRL6_REG\n",
  1631. __func__);
  1632. goto unhandled;
  1633. }
  1634. ret = sii9234_cbus_init(sii9234);
  1635. if (ret < 0)
  1636. goto unhandled;
  1637. ret = mhl_tx_write_reg(sii9234, MHL_TX_DISC_CTRL1_REG, 0x27);
  1638. if (ret < 0)
  1639. goto unhandled;
  1640. /* Enable Auto soft reset on SCDT = 0*/
  1641. ret = mhl_tx_write_reg(sii9234, 0x05, 0x04);
  1642. if (ret < 0)
  1643. goto unhandled;
  1644. /* HDMI Transcode mode enable*/
  1645. ret = mhl_tx_write_reg(sii9234, 0x0D, 0x1C);
  1646. if (ret < 0)
  1647. goto unhandled;
  1648. ret = mhl_tx_write_reg(sii9234, MHL_TX_INTR4_ENABLE_REG,
  1649. RGND_READY_MASK | CBUS_LKOUT_MASK |
  1650. MHL_DISC_FAIL_MASK | MHL_EST_MASK);
  1651. if (ret < 0)
  1652. goto unhandled;
  1653. ret = mhl_tx_write_reg(sii9234, MHL_TX_INTR1_ENABLE_REG,
  1654. (1<<5) | (1<<6));
  1655. if (ret < 0)
  1656. goto unhandled;
  1657. /* this point is very importand before megsure RGND impedance*/
  1658. force_usb_id_switch_open(sii9234);
  1659. ret = mhl_tx_clear_reg(sii9234, MHL_TX_DISC_CTRL4_REG,
  1660. (1<<7) | (1<<6) | (1<<5) | (1<<4));
  1661. if (ret < 0)
  1662. goto unhandled;
  1663. ret = mhl_tx_clear_reg(sii9234, MHL_TX_DISC_CTRL5_REG, (1<<1) | (1<<0));
  1664. if (ret < 0)
  1665. goto unhandled;
  1666. release_usb_id_switch_open(sii9234);
  1667. /*end of this*/
  1668. pr_debug("sii9234: waiting for RGND measurement\n");
  1669. sii9234_enable_irq();
  1670. /* SiI9244 Programmer's Reference Section 2.4.3
  1671. * State : RGND Ready
  1672. */
  1673. sii9234_mutex_unlock(&sii9234->lock);
  1674. #ifndef CONFIG_MHL_D3_SUPPORT
  1675. ret = wait_event_timeout(sii9234->wq,
  1676. ((sii9234->rgnd != RGND_UNKNOWN) ||
  1677. mhl_state_is_error(sii9234->state)),
  1678. msecs_to_jiffies(T_WAIT_TIMEOUT_RGND_INT*1.5));
  1679. sii9234_mutex_lock(&sii9234->lock);
  1680. if (ret == 0 || mhl_state_is_error(sii9234->state))
  1681. goto unhandled;
  1682. if (sii9234->rgnd != RGND_1K)
  1683. goto unhandled;
  1684. sii9234_mutex_unlock(&sii9234->lock);
  1685. #endif
  1686. pr_debug("sii9234: waiting for detection\n");
  1687. ret = wait_event_timeout(sii9234->wq,
  1688. sii9234->state != STATE_DISCONNECTED,
  1689. msecs_to_jiffies(T_WAIT_TIMEOUT_DISC_INT*2));
  1690. sii9234_mutex_lock(&sii9234->lock);
  1691. if (ret == 0) {
  1692. pr_err("[ERROR] %s() - wait detection\n", __func__);
  1693. goto unhandled;
  1694. }
  1695. if (sii9234->state == STATE_DISCOVERY_FAILED) {
  1696. pr_err("[ERROR] %s() - state == STATE_DISCOVERY_FAILED\n",
  1697. __func__);
  1698. goto unhandled;
  1699. }
  1700. if (mhl_state_is_error(sii9234->state))
  1701. goto unhandled;
  1702. sii9234_mutex_unlock(&sii9234->lock);
  1703. pr_info("sii9234: Established & start to moniter RSEN\n");
  1704. /*CTS 3.3.14.3 Discovery;Sink Never Drives MHL+/- HIGH*/
  1705. /*MHL SPEC 8.2.1.1.1;Transition SRC4-SRC7*/
  1706. if (rsen_state_timer_out(sii9234) < 0)
  1707. goto exit;
  1708. sii9234->claimed = true;
  1709. sii9234_mutex_lock(&sii9234->lock);
  1710. ret = cbus_write_reg(sii9234,
  1711. CBUS_INTR1_ENABLE_REG,
  1712. MSC_RESP_ABORT_MASK |
  1713. MSC_REQ_ABORT_MASK |
  1714. MSC_REQ_DONE_MASK |
  1715. MSC_MSG_RECD_MASK |
  1716. CBUS_DDC_ABORT_MASK);
  1717. if (ret < 0)
  1718. goto unhandled;
  1719. ret = cbus_write_reg(sii9234,
  1720. CBUS_INTR2_ENABLE_REG,
  1721. WRT_STAT_RECD_MASK |
  1722. SET_INT_RECD_MASK);
  1723. if (ret < 0)
  1724. goto unhandled;
  1725. sii9234_mutex_unlock(&sii9234->lock);
  1726. #ifdef CONFIG_MHL_NEW_CBUS_MSC_CMD
  1727. ret = wait_event_timeout(sii9234->wq,
  1728. sii9234->dcap_ready_status,
  1729. msecs_to_jiffies(500));
  1730. if (ret == 0) {
  1731. /*UNKNOWN*/
  1732. sii9234->vbus_owner = 0;
  1733. pr_info("dcap_timeout err, dcap_staus:%d\n",
  1734. sii9234->dcap_ready_status);
  1735. } else {
  1736. /*SAMSUNG DEVICE_ID 0x1134:dongle, 0x1234:dock*/
  1737. if (sii9234->devcap.device_id == SS_MHL_DONGLE_DEV_ID ||
  1738. sii9234->devcap.device_id == SS_MHL_DOCK_DEV_ID)
  1739. sii9234->vbus_owner = sii9234->devcap.reserved_data;
  1740. else
  1741. sii9234->vbus_owner = 0;
  1742. }
  1743. pr_info("device_id:0x%4x, vbus_owner:%d\n",
  1744. sii9234->devcap.device_id, sii9234->vbus_owner);
  1745. #else
  1746. /*UNKNOWN*/
  1747. sii9234->vbus_owner = 0;
  1748. #endif
  1749. /*send some data for VBUS SRC such a TA or USB or UNKNOWN*/
  1750. if (sii9234->pdata->vbus_present)
  1751. #ifdef CONFIG_MHL_NEW_CBUS_MSC_CMD
  1752. sii9234->pdata->vbus_present(true , sii9234->vbus_owner);
  1753. #else
  1754. sii9234->pdata->vbus_present(true);
  1755. #endif
  1756. goto exit;
  1757. unhandled:
  1758. pr_info("sii9234: Detection failed");
  1759. if (sii9234->state == STATE_DISCONNECTED) {
  1760. pr_cont(" (timeout)");
  1761. mutex_unlock(&sii9234->lock);
  1762. #ifndef CONFIG_MHL_D3_SUPPORT
  1763. mhl_onoff_ex(0);
  1764. #endif
  1765. goto exit;
  1766. } else if (sii9234->state == STATE_DISCOVERY_FAILED)
  1767. pr_cont(" (discovery failed)");
  1768. else if (sii9234->state == STATE_CBUS_LOCKOUT)
  1769. pr_cont(" (cbus_lockout)");
  1770. pr_cont("\n");
  1771. /*mhl spec: 8.3.3, if discovery failed, must retry discovering*/
  1772. if ((sii9234->state == STATE_DISCOVERY_FAILED) &&
  1773. (sii9234->rgnd == RGND_1K)) {
  1774. pr_cont("Discovery failed but RGND_1K impedence");
  1775. pr_cont(" restart detection_callback");
  1776. #ifdef CONFIG_MHL_D3_SUPPORT
  1777. INIT_WORK(&sii9234->rgnd_work, goto_d3);
  1778. sii9234_disable_irq();
  1779. schedule_work(&sii9234->rgnd_work);
  1780. #else
  1781. /* INIT_WORK(&sii9234->redetect_work,
  1782. sii9234_detection_callback); */
  1783. sii9234_disable_irq();
  1784. if (sii9234->pdata->hw_reset)
  1785. sii9234->pdata->hw_reset();
  1786. schedule_work(&sii9234->redetect_work);
  1787. #endif
  1788. }
  1789. sii9234_mutex_unlock(&sii9234->lock);
  1790. exit:
  1791. pr_debug("%s end\n", __func__);
  1792. }
  1793. static void sii9234_cancel_callback(void)
  1794. {
  1795. struct sii9234_data *sii9234 = dev_get_drvdata(sii9244_mhldev);
  1796. sii9234_mutex_lock(&sii9234->lock);
  1797. sii9234_power_down(sii9234);
  1798. sii9234_mutex_unlock(&sii9234->lock);
  1799. }
  1800. static void save_cbus_pkt_to_buffer(struct sii9234_data *sii9234)
  1801. {
  1802. int index;
  1803. for (index = 0; index < CBUS_PKT_BUF_COUNT; index++)
  1804. if (sii9234->cbus_pkt_buf[index].status == false)
  1805. break;
  1806. if (index == CBUS_PKT_BUF_COUNT) {
  1807. pr_debug("sii9234: Error save_cbus_pkt Buffer Full\n");
  1808. index -= 1; /*adjust index*/
  1809. }
  1810. pr_debug("sii9234: save_cbus_pkt_to_buffer index = %d\n", index);
  1811. memcpy(&sii9234->cbus_pkt_buf[index], &sii9234->cbus_pkt,
  1812. sizeof(struct cbus_packet));
  1813. sii9234->cbus_pkt_buf[index].status = true;
  1814. }
  1815. #ifndef CONFIG_MHL_NEW_CBUS_MSC_CMD
  1816. static void cbus_command_response(struct sii9234_data *sii9234)
  1817. {
  1818. u8 value, offset = 0;
  1819. mutex_lock(&sii9234->cbus_lock);
  1820. pr_debug("sii9234: cbus_command_response\n");
  1821. switch (sii9234->cbus_pkt.command) {
  1822. case CBUS_MSC_MSG:
  1823. pr_debug("sii9234: cbus_command_response Received ACK for CBUS_MSC_MSG\n");
  1824. #ifdef CONFIG_SII9234_RCP
  1825. if (sii9234->cbus_pkt.data[0] == MSG_RCPE &&
  1826. sii9234->cbus_pkt.data[1] == 0x01) {
  1827. sii9234->cbus_pkt.command = CBUS_IDLE;
  1828. mutex_unlock(&sii9234->cbus_lock);
  1829. cbus_command_request(sii9234, CBUS_MSC_MSG, MSG_RCPK,
  1830. sii9234->error_key);
  1831. return;
  1832. }
  1833. #endif
  1834. break;
  1835. case CBUS_WRITE_STAT:
  1836. pr_debug("sii9234: cbus_command_response CBUS_WRITE_STAT\n");
  1837. cbus_read_reg(sii9234, CBUS_MSC_FIRST_DATA_IN_REG,
  1838. &sii9234->cbus_pkt.data[0]);
  1839. break;
  1840. case CBUS_SET_INT:
  1841. pr_debug("sii9234: cbus_command_response CBUS_SET_INT\n");
  1842. if (sii9234->cbus_pkt.offset == MHL_RCHANGE_INT &&
  1843. sii9234->cbus_pkt.data[0] == MHL_INT_DSCR_CHG) {
  1844. /*Write burst final step... Req->GRT->Write->DSCR*/
  1845. pr_debug("sii9234: MHL_RCHANGE_INT & MHL_INT_DSCR_CHG\n");
  1846. } else if (sii9234->cbus_pkt.offset == MHL_RCHANGE_INT &&
  1847. sii9234->cbus_pkt.data[0] == MHL_INT_DCAP_CHG) {
  1848. pr_debug("sii9234: MHL_RCHANGE_INT & MHL_INT_DCAP_CHG\n");
  1849. sii9234->cbus_pkt.command = CBUS_IDLE;
  1850. mutex_unlock(&sii9234->cbus_lock);
  1851. cbus_command_request(sii9234, CBUS_WRITE_STAT,
  1852. MHL_STATUS_REG_CONNECTED_RDY,
  1853. MHL_STATUS_DCAP_READY);
  1854. return;
  1855. }
  1856. break;
  1857. case CBUS_WRITE_BURST:
  1858. pr_debug("sii9234: cbus_command_response MHL_WRITE_BURST\n");
  1859. sii9234->cbus_pkt.command = CBUS_IDLE;
  1860. mutex_unlock(&sii9234->cbus_lock);
  1861. cbus_command_request(sii9234, CBUS_SET_INT,
  1862. MHL_RCHANGE_INT, MHL_INT_DSCR_CHG);
  1863. return;
  1864. case CBUS_READ_DEVCAP:
  1865. pr_debug("sii9234: cbus_command_response CBUS_READ_DEVCAP\n");
  1866. cbus_read_reg(sii9234, CBUS_MSC_FIRST_DATA_IN_REG,
  1867. &value);
  1868. switch (sii9234->cbus_pkt.offset) {
  1869. case DEVCAP_MHL_VERSION:
  1870. sii9234->devcap.mhl_ver = value;
  1871. pr_debug("sii9234: MHL_VERSION: %X\n", value);
  1872. break;
  1873. case DEVCAP_DEV_CAT:
  1874. if (value & MHL_DEV_CATEGORY_POW_BIT)
  1875. pr_debug("sii9234: CAT=POWERED");
  1876. else
  1877. pr_debug("sii9234: CAT=UNPOWERED");
  1878. break;
  1879. case DEVCAP_ADOPTER_ID_H:
  1880. sii9234->devcap.adopter_id = (value & 0xFF) << 0x8;
  1881. pr_debug("sii9234: DEVCAP_ADOPTER_ID_H = %X\n", value);
  1882. break;
  1883. case DEVCAP_ADOPTER_ID_L:
  1884. sii9234->devcap.adopter_id |= value & 0xFF;
  1885. pr_debug("sii9234: DEVCAP_ADOPTER_ID_L = %X\n", value);
  1886. break;
  1887. case DEVCAP_VID_LINK_MODE:
  1888. sii9234->devcap.vid_link_mode = 0x3F & value;
  1889. pr_debug("sii9234: MHL_CAP_VID_LINK_MODE = %d\n",
  1890. sii9234->devcap.vid_link_mode);
  1891. break;
  1892. case DEVCAP_AUD_LINK_MODE:
  1893. sii9234->devcap.aud_link_mode = 0x03 & value;
  1894. pr_debug("sii9234: DEVCAP_AUD_LINK_MODE =%d\n",
  1895. sii9234->devcap.aud_link_mode);
  1896. break;
  1897. case DEVCAP_VIDEO_TYPE:
  1898. sii9234->devcap.video_type = 0x8F & value;
  1899. pr_debug("sii9234: DEVCAP_VIDEO_TYPE =%d\n",
  1900. sii9234->devcap.video_type);
  1901. break;
  1902. case DEVCAP_LOG_DEV_MAP:
  1903. sii9234->devcap.log_dev_map = value;
  1904. pr_debug("sii9234: DEVCAP_LOG_DEV_MAP =%d\n",
  1905. sii9234->devcap.log_dev_map);
  1906. break;
  1907. case DEVCAP_BANDWIDTH:
  1908. sii9234->devcap.bandwidth = value;
  1909. pr_debug("sii9234: DEVCAP_BANDWIDTH =%d\n",
  1910. sii9234->devcap.bandwidth);
  1911. break;
  1912. case DEVCAP_DEV_FEATURE_FLAG:
  1913. if ((value & MHL_FEATURE_RCP_SUPPORT) == 0)
  1914. pr_debug("sii9234: FEATURE_FLAG=RCP");
  1915. if ((value & MHL_FEATURE_RAP_SUPPORT) == 0)
  1916. pr_debug("sii9234: FEATURE_FLAG=RAP\n");
  1917. if ((value & MHL_FEATURE_SP_SUPPORT) == 0)
  1918. pr_debug("sii9234: FEATURE_FLAG=SP\n");
  1919. break;
  1920. case DEVCAP_DEVICE_ID_H:
  1921. sii9234->devcap.device_id = (value & 0xFF) << 0x8;
  1922. pr_info("sii9234: DEVICE_ID_H=0x%x\n", value);
  1923. offset = DEVCAP_DEVICE_ID_L;
  1924. break;
  1925. case DEVCAP_DEVICE_ID_L:
  1926. sii9234->devcap.device_id |= value & 0xFF;
  1927. pr_info("sii9234: DEVICE_ID_L=0x%x\n", value);
  1928. break;
  1929. case DEVCAP_SCRATCHPAD_SIZE:
  1930. sii9234->devcap.scratchpad_size = value;
  1931. pr_debug("sii9234: DEVCAP_SCRATCHPAD_SIZE =%d\n",
  1932. sii9234->devcap.scratchpad_size);
  1933. break;
  1934. case DEVCAP_INT_STAT_SIZE:
  1935. sii9234->devcap.int_stat_size = value;
  1936. pr_debug("sii9234: DEVCAP_INT_STAT_SIZE =%d\n",
  1937. sii9234->devcap.int_stat_size);
  1938. break;
  1939. case DEVCAP_RESERVED:
  1940. pr_info("sii9234: DEVCAP_RESERVED : %d\n", value);
  1941. break;
  1942. case DEVCAP_DEV_STATE:
  1943. pr_debug("sii9234: DEVCAP_DEV_STATE\n");
  1944. break;
  1945. default:
  1946. pr_debug("sii9234: DEVCAP DEFAULT\n");
  1947. break;
  1948. }
  1949. break;
  1950. default:
  1951. pr_debug("sii9234: error: cbus_command_response cannot handle...\n");
  1952. }
  1953. sii9234->cbus_pkt.command = CBUS_IDLE;
  1954. mutex_unlock(&sii9234->cbus_lock);
  1955. if (offset)
  1956. cbus_command_request(sii9234, CBUS_READ_DEVCAP,
  1957. offset, 0x00);
  1958. }
  1959. #endif
  1960. #ifdef DEBUG_MHL
  1961. static void cbus_command_response_dbg_msg(struct sii9234_data *sii9234,
  1962. u8 index)
  1963. {
  1964. /*Added to debugcbus_pkt_buf*/
  1965. pr_info("sii9234: cbus_pkt_buf[index].command = %d",
  1966. sii9234->cbus_pkt_buf[index].command);
  1967. pr_info("sii9234->cbus_pkt.command = %d\n",
  1968. sii9234->cbus_pkt.command);
  1969. pr_info("sii9234: cbus_pkt_buf[index].data[0] = %d",
  1970. sii9234->cbus_pkt_buf[index].data[0]);
  1971. pr_info("sii9234->cbus_pkt.data[0] = %d\n",
  1972. sii9234->cbus_pkt.data[0]);
  1973. pr_info("sii9234: cbus_pkt_buf[index].data[1] = %d",
  1974. sii9234->cbus_pkt_buf[index].data[1]);
  1975. pr_info("sii9234->cbus_pkt.data[1] = %d\n",
  1976. sii9234->cbus_pkt.data[1]);
  1977. pr_info("sii9234: cbus_pkt_buf[index].offset = %d",
  1978. sii9234->cbus_pkt_buf[index].offset);
  1979. pr_info("sii9234->cbus_pkt.offset = %d\n",
  1980. sii9234->cbus_pkt.offset);
  1981. }
  1982. #endif
  1983. #ifndef CONFIG_MHL_NEW_CBUS_MSC_CMD
  1984. static void cbus_command_response_all(struct sii9234_data *sii9234)
  1985. {
  1986. u8 index;
  1987. struct cbus_packet cbus_pkt_process_buf[CBUS_PKT_BUF_COUNT];
  1988. pr_debug("sii9234: cbus_command_response_all for All requests\n");
  1989. /*take bkp of cbus_pkt_buf*/
  1990. memcpy(cbus_pkt_process_buf, sii9234->cbus_pkt_buf,
  1991. sizeof(cbus_pkt_process_buf));
  1992. /*clear cbus_pkt_buf to hold next request*/
  1993. memset(sii9234->cbus_pkt_buf, 0x00, sizeof(sii9234->cbus_pkt_buf));
  1994. /*process all previous requests*/
  1995. for (index = 0; index < CBUS_PKT_BUF_COUNT; index++) {
  1996. if (cbus_pkt_process_buf[index].status == true) {
  1997. memcpy(&sii9234->cbus_pkt, &cbus_pkt_process_buf[index],
  1998. sizeof(struct cbus_packet));
  1999. cbus_command_response(sii9234);
  2000. #ifdef DEBUG_MHL
  2001. /*print cbus_cmd messg*/
  2002. cbus_command_response_dbg_msg(sii9234, index);
  2003. #endif
  2004. }
  2005. }
  2006. }
  2007. #endif
  2008. static bool cbus_command_request(struct sii9234_data *sii9234,
  2009. enum cbus_command command, u8 offset, u8 data)
  2010. {
  2011. u8 start_bit = 0;
  2012. mutex_lock(&sii9234->cbus_lock);
  2013. if (sii9234->state != STATE_ESTABLISHED) {
  2014. pr_debug("sii9234: cbus_command_request without establish\n");
  2015. pr_debug("sii9234: ==> command:0x%X, offset:0x%X",
  2016. command, offset);
  2017. mutex_unlock(&sii9234->cbus_lock);
  2018. return -EINVAL;
  2019. }
  2020. sii9234->cbus_pkt.command = command;
  2021. sii9234->cbus_pkt.offset = offset;
  2022. if (command == CBUS_MSC_MSG)
  2023. sii9234->cbus_pkt.data[0] = offset;
  2024. else
  2025. sii9234->cbus_pkt.data[0] = data;
  2026. pr_debug("sii9234: cbus_command_request Sending MSC_MSG SubCommand=%d"
  2027. , sii9234->cbus_pkt.offset);
  2028. pr_debug(",key-code=%d\n", sii9234->cbus_pkt.data[0]);
  2029. cbus_write_reg(sii9234, CBUS_MSC_OFFSET_REG,
  2030. sii9234->cbus_pkt.offset);
  2031. cbus_write_reg(sii9234, CBUS_MSC_FIRST_DATA_OUT_REG,
  2032. sii9234->cbus_pkt.data[0]);
  2033. switch (sii9234->cbus_pkt.command) {
  2034. case CBUS_SET_INT:
  2035. pr_debug("sii9234: cbus_command_request CBUS_SET_INT\n");
  2036. start_bit = START_BIT_WRITE_STAT_INT;
  2037. break;
  2038. case CBUS_WRITE_STAT:
  2039. pr_debug("sii9234: cbus_command_request CBUS_WRITE_STAT\n");
  2040. start_bit = START_BIT_WRITE_STAT_INT;
  2041. break;
  2042. case CBUS_MSC_MSG:
  2043. /*treat offset as data[0] in case of CBUS_MSC_MSG*/
  2044. sii9234->cbus_pkt.data[0] = offset;
  2045. sii9234->cbus_pkt.data[1] = data;
  2046. pr_debug("sii9234: cbus_command_request CBUS_MSC_MSG SubCommand=%d"
  2047. , sii9234->cbus_pkt.data[0]);
  2048. pr_debug(",key-code=%d\n", sii9234->cbus_pkt.data[1]);
  2049. cbus_write_reg(sii9234, CBUS_MSC_SECOND_DATA_OUT_REG,
  2050. sii9234->cbus_pkt.data[1]);
  2051. cbus_write_reg(sii9234, CBUS_MSC_OFFSET_REG,
  2052. sii9234->cbus_pkt.command);
  2053. start_bit = START_BIT_MSC_MSG;
  2054. break;
  2055. case CBUS_READ_DEVCAP:
  2056. pr_debug("sii9234: cbus_command_request CBUS_READ_DEVCAP\n");
  2057. start_bit = START_BIT_READ_DEVCAP;
  2058. break;
  2059. case CBUS_WRITE_BURST:
  2060. pr_debug("sii9234: cbus_command_request CBUS_WRITE_BURST\n");
  2061. start_bit = START_BIT_WRITE_BURST;
  2062. break;
  2063. case CBUS_GET_STATE:
  2064. case CBUS_GET_VENDOR_ID:
  2065. case CBUS_SET_HPD:
  2066. case CBUS_CLR_HPD:
  2067. case CBUS_GET_MSC_ERR_CODE:
  2068. case CBUS_GET_SC3_ERR_CODE:
  2069. case CBUS_GET_SC1_ERR_CODE:
  2070. case CBUS_GET_DDC_ERR_CODE:
  2071. cbus_write_reg(sii9234, CBUS_MSC_OFFSET_REG,
  2072. sii9234->cbus_pkt.command);
  2073. start_bit = START_BIT_MSC_RESERVED;
  2074. break;
  2075. default:
  2076. pr_debug("sii9234: error send cbus command fail\n");
  2077. mutex_unlock(&sii9234->cbus_lock);
  2078. return false;
  2079. }
  2080. pr_debug("sii9234: startbit = %d\n", start_bit);
  2081. cbus_write_reg(sii9234, CBUS_MSC_COMMAND_START_REG, start_bit);
  2082. save_cbus_pkt_to_buffer(sii9234);
  2083. mutex_unlock(&sii9234->cbus_lock);
  2084. return true;
  2085. }
  2086. static u8 sii9234_tmds_control(struct sii9234_data *sii9234, bool enable)
  2087. {
  2088. u8 ret;
  2089. if (enable) {
  2090. #ifdef __CONFIG_RSEN_LOST_PATCH__
  2091. ret = mhl_tx_write_reg(sii9234, MHL_TX_MHLTX_CTL2_REG, 0xFC);
  2092. if (ret < 0)
  2093. return ret;
  2094. #endif
  2095. ret = mhl_tx_set_reg(sii9234, MHL_TX_TMDS_CCTRL, (1<<4));
  2096. if (ret < 0)
  2097. return ret;
  2098. pr_debug("sii9234: MHL HPD High, enabled TMDS\n");
  2099. ret = mhl_tx_set_reg(sii9234, MHL_TX_INT_CTRL_REG,
  2100. (1<<4) | (1<<5));
  2101. if (ret < 0)
  2102. return ret;
  2103. } else {
  2104. ret = mhl_tx_clear_reg(sii9234, MHL_TX_TMDS_CCTRL, (1<<4));
  2105. if (ret < 0)
  2106. return ret;
  2107. pr_debug("sii9234 MHL HPD low, disabled TMDS\n");
  2108. ret = mhl_tx_clear_reg(sii9234, MHL_TX_INT_CTRL_REG,
  2109. (1<<4) | (1<<5));
  2110. if (ret < 0)
  2111. return ret;
  2112. #ifdef __CONFIG_RSEN_LOST_PATCH__
  2113. ret = mhl_tx_write_reg(sii9234, MHL_TX_MHLTX_CTL2_REG, 0xC0);
  2114. if (ret < 0)
  2115. return ret;
  2116. #endif
  2117. }
  2118. return ret;
  2119. }
  2120. static irqreturn_t sii9234_irq_thread(int irq, void *data)
  2121. {
  2122. struct sii9234_data *sii9234 = data;
  2123. int ret;
  2124. u8 intr1, intr4, value = 0x0;
  2125. u8 intr1_en, intr4_en = 0x0;
  2126. bool release_otg = false;
  2127. u8 cbus_intr1, cbus_intr2 = 0x0;
  2128. u8 mhl_poweroff = 0;
  2129. void (*cbus_resp_callback)(struct sii9234_data *) = NULL;
  2130. if (!sii9234) {
  2131. pr_err("%s: sii9234 is NULL & skipp this rutine\n", __func__);
  2132. return IRQ_HANDLED;
  2133. }
  2134. d3_mode_rgnd_state = 1;
  2135. msleep(30);
  2136. sii9234_mutex_lock(&sii9234->lock);
  2137. ret = mhl_tx_read_reg(sii9234, MHL_TX_INTR1_REG, &intr1);
  2138. if (ret < 0) {
  2139. printk(KERN_ERR
  2140. "[ERROR] %s():%d read MHL_TX_INTR1_REG failed !\n",
  2141. __func__, __LINE__);
  2142. goto i2c_error_exit;
  2143. }
  2144. ret = mhl_tx_read_reg(sii9234, MHL_TX_INTR4_REG, &intr4);
  2145. if (ret < 0) {
  2146. printk(KERN_ERR
  2147. "[ERROR] %s():%d read MHL_TX_INTR4_REG failed !\n",
  2148. __func__, __LINE__);
  2149. goto i2c_error_exit;
  2150. }
  2151. ret = mhl_tx_read_reg(sii9234, MHL_TX_INTR1_ENABLE_REG, &intr1_en);
  2152. if (ret < 0) {
  2153. printk(KERN_ERR
  2154. "[ERROR] %s():%d read MHL_TX_INTR1_ENABLE_REG failed !\n",
  2155. __func__, __LINE__);
  2156. goto i2c_error_exit;
  2157. }
  2158. ret = mhl_tx_read_reg(sii9234, MHL_TX_INTR4_ENABLE_REG, &intr4_en);
  2159. if (ret < 0) {
  2160. printk(KERN_ERR
  2161. "[ERROR] %s():%d read MHL_TX_INTR4_ENABLE_REG failed !\n",
  2162. __func__, __LINE__);
  2163. goto i2c_error_exit;
  2164. }
  2165. ret = cbus_read_reg(sii9234, CBUS_INT_STATUS_1_REG, &cbus_intr1);
  2166. if (ret < 0) {
  2167. printk(KERN_ERR
  2168. "[ERROR] %s():%d read CBUS_INT_STATUS_1_REG failed !\n",
  2169. __func__, __LINE__);
  2170. goto i2c_error_exit;
  2171. }
  2172. ret = cbus_read_reg(sii9234, CBUS_INT_STATUS_2_REG, &cbus_intr2);
  2173. if (ret < 0) {
  2174. printk(KERN_ERR
  2175. "[ERROR] %s():%d read CBUS_INT_STATUS_2_REG failed !\n",
  2176. __func__, __LINE__);
  2177. goto i2c_error_exit;
  2178. }
  2179. pr_debug("sii9234: irq %02x/%02x %02x/%02x %02x/%02x\n",
  2180. intr1, intr1_en,
  2181. intr4, intr4_en,
  2182. cbus_intr1, cbus_intr2);
  2183. if (intr4 & RGND_READY_INT) {
  2184. #ifdef CONFIG_MHL_D3_SUPPORT
  2185. if (sii9234_callback_sched == 0) {
  2186. pr_info("rgnd interrupt debug\n");
  2187. /* INIT_WORK(&sii9234->redetect_work,
  2188. sii9234_detection_callback); */
  2189. sii9234_disable_irq();
  2190. if (sii9234->pdata->hw_reset)
  2191. sii9234->pdata->hw_reset();
  2192. schedule_work(&sii9234->rgnd_work);
  2193. goto err_exit;
  2194. }
  2195. #endif
  2196. ret = mhl_tx_read_reg(sii9234, MHL_TX_STAT2_REG, &value);
  2197. if (ret < 0) {
  2198. dev_err(&sii9234->pdata->mhl_tx_client->dev,
  2199. "STAT2 reg, err %d\n", ret);
  2200. goto err_exit;
  2201. }
  2202. switch (value & RGND_INTP_MASK) {
  2203. case RGND_INTP_OPEN:
  2204. pr_info("sii9234: RGND Open\n");
  2205. sii9234->rgnd = RGND_OPEN;
  2206. break;
  2207. case RGND_INTP_1K:
  2208. pr_info("sii9234: RGND 1K\n");
  2209. /* After applying RGND patch, there is some issue
  2210. about discovry failure
  2211. This point is add to fix that problem*/
  2212. ret = mhl_tx_set_reg(sii9234, MHL_TX_DISC_CTRL4_REG,
  2213. 0x8C);
  2214. if (ret < 0) {
  2215. printk(KERN_ERR
  2216. "[ERROR] %s():%d write MHL_TX_DISC_CTRL4_REG failed !\n",
  2217. __func__, __LINE__);
  2218. goto i2c_error_exit;
  2219. }
  2220. ret = mhl_tx_write_reg(sii9234,
  2221. MHL_TX_DISC_CTRL5_REG, 0x77);
  2222. if (ret < 0) {
  2223. printk(KERN_ERR
  2224. "[ERROR] %s():%d write MHL_TX_DISC_CTRL5_REG failed !\n",
  2225. __func__, __LINE__);
  2226. goto i2c_error_exit;
  2227. }
  2228. ret = mhl_tx_set_reg(sii9234,
  2229. MHL_TX_DISC_CTRL6_REG, 0x05);
  2230. if (ret < 0) {
  2231. printk(KERN_ERR
  2232. "[ERROR] %s():%d write MHL_TX_DISC_CTRL6_REG failed !\n",
  2233. __func__, __LINE__);
  2234. goto i2c_error_exit;
  2235. }
  2236. usleep_range(T_SRC_VBUS_CBUS_TO_STABLE * USEC_PER_MSEC,
  2237. T_SRC_VBUS_CBUS_TO_STABLE * USEC_PER_MSEC);
  2238. /* end of this*/
  2239. pr_debug("sii9234: %s() send wakeup pulse\n", __func__);
  2240. ret = mhl_send_wake_pulses(sii9234);
  2241. if (ret < 0) {
  2242. pr_err("[ERROR] sii9234: sending wake pulses error\n");
  2243. goto err_exit;
  2244. }
  2245. sii9234->rgnd = RGND_1K;
  2246. break;
  2247. case RGND_INTP_2K:
  2248. pr_info("sii9234: RGND 2K\n");
  2249. sii9234->rgnd = RGND_2K;
  2250. break;
  2251. case RGND_INTP_SHORT:
  2252. pr_info("sii9234: RGND Short\n");
  2253. sii9234->rgnd = RGND_SHORT;
  2254. break;
  2255. };
  2256. if (sii9234->rgnd != RGND_1K) {
  2257. mhl_poweroff = 1; /*Power down mhl chip */
  2258. goto err_exit;
  2259. }
  2260. }
  2261. if (intr4 & CBUS_LKOUT_INT) { /* 1<<4 */
  2262. pr_debug("%s(): CBUS Lockout Interrupt\n", __func__);
  2263. sii9234->state = STATE_CBUS_LOCKOUT;
  2264. }
  2265. if (intr4 & MHL_DISC_FAIL_INT) { /* 1<<3 */
  2266. printk(KERN_ERR "[ERROR] %s(): MHL_DISC_FAIL_INT\n", __func__);
  2267. sii9234->state = STATE_DISCOVERY_FAILED;
  2268. goto err_exit;
  2269. }
  2270. if (intr4 & MHL_EST_INT) {
  2271. pr_debug("sii9234: mhl est interrupt %d\n", value);
  2272. /* discovery override */
  2273. ret = mhl_tx_write_reg(sii9234, MHL_TX_MHLTX_CTL1_REG, 0x10);
  2274. if (ret < 0) {
  2275. printk(KERN_ERR
  2276. "[ERROR] %s():%d write MHL_TX_MHLTX_CTRL1_REG failed !\n",
  2277. __func__, __LINE__);
  2278. goto i2c_error_exit;
  2279. }
  2280. /* increase DDC translation layer timer (byte mode) */
  2281. ret = cbus_write_reg(sii9234, 0x07, 0x32);
  2282. if (ret < 0) {
  2283. printk(KERN_ERR
  2284. "[ERROR] %s():%d cbus_write_reg failed !\n",
  2285. __func__, __LINE__);
  2286. goto i2c_error_exit;
  2287. }
  2288. ret = cbus_set_reg(sii9234, 0x44, 1 << 1);
  2289. if (ret < 0) {
  2290. printk(KERN_ERR
  2291. "[ERROR] %s():%d cbus_set_reg failed !\n",
  2292. __func__, __LINE__);
  2293. goto i2c_error_exit;
  2294. }
  2295. /* Keep the discovery enabled. Need RGND interrupt */
  2296. ret = mhl_tx_set_reg(sii9234, MHL_TX_DISC_CTRL1_REG, (1<<0));
  2297. if (ret < 0) {
  2298. printk(KERN_ERR
  2299. "[ERROR] %s():%d mhl_tx_set_reg failed !\n",
  2300. __func__, __LINE__);
  2301. goto i2c_error_exit;
  2302. }
  2303. sii9234->state = STATE_ESTABLISHED;
  2304. #ifndef CONFIG_MHL_NEW_CBUS_MSC_CMD
  2305. cbus_command_request(sii9234, CBUS_SET_INT,
  2306. MHL_RCHANGE_INT, MHL_INT_DCAP_CHG);
  2307. #else
  2308. sii9234_enqueue_msc_work(sii9234, CBUS_SET_INT,
  2309. MHL_RCHANGE_INT, MHL_INT_DCAP_CHG, 0x0);
  2310. #endif
  2311. ret = mhl_tx_write_reg(sii9234, MHL_TX_INTR1_ENABLE_REG,
  2312. RSEN_CHANGE_INT_MASK | HPD_CHANGE_INT_MASK);
  2313. }
  2314. if (intr1 & HPD_CHANGE_INT) {
  2315. ret = cbus_read_reg(sii9234, MSC_REQ_ABORT_REASON_REG, &value);
  2316. if (ret < 0) {
  2317. printk(KERN_ERR
  2318. "[ERROR] %s():%d cbus_read_reg failed !\n",
  2319. __func__, __LINE__);
  2320. goto i2c_error_exit;
  2321. }
  2322. if (value & SET_HPD_DOWNSTREAM) {
  2323. pr_info("%s() hpd high\n", __func__);
  2324. /* Downstream HPD High */
  2325. /* Do we need to send HPD upstream using
  2326. * Register 0x79(page0)? Is HPD need to be overriden??
  2327. * TODO: See if we need code for overriding HPD OUT
  2328. * as per Page 0,0x79 Register
  2329. */
  2330. sii9234->mhl_status_value.sink_hpd = true;
  2331. #ifdef __CONFIG_USE_TIMER__
  2332. if (cbus_command_abort_state == 1) {
  2333. pr_info("cbus_command_mod_timer\n");
  2334. mod_timer(&sii9234->cbus_command_timer,
  2335. jiffies + 2*HZ);
  2336. cbus_command_abort_state = 0;
  2337. } else
  2338. #endif
  2339. #ifndef CONFIG_MHL_NEW_CBUS_MSC_CMD
  2340. cbus_command_request(sii9234, CBUS_WRITE_STAT,
  2341. CBUS_LINK_CONTROL_2_REG,
  2342. sii9234->mhl_status_value.linkmode);
  2343. #else
  2344. sii9234_enqueue_msc_work(sii9234, CBUS_WRITE_STAT,
  2345. CBUS_LINK_CONTROL_2_REG,
  2346. sii9234->mhl_status_value.linkmode, 0x0);
  2347. #endif
  2348. /* Enable TMDS */
  2349. sii9234_tmds_control(sii9234, true);
  2350. /*turn on&off hpd festure for only QCT HDMI*/
  2351. mhl_hpd_handler(true);
  2352. } else {
  2353. pr_info("sii9234: hpd low\n");
  2354. /*Downstream HPD Low*/
  2355. /* Similar to above comments.
  2356. * TODO:Do we need to override HPD OUT value
  2357. * and do we need to disable TMDS here?
  2358. */
  2359. sii9234->mhl_status_value.sink_hpd = false;
  2360. /* Disable TMDS */
  2361. sii9234_tmds_control(sii9234, false);
  2362. }
  2363. }
  2364. if (intr1 & RSEN_CHANGE_INT) {
  2365. /* work_around code to handle worng interrupt*/
  2366. if (sii9234->rgnd != RGND_1K) {
  2367. pr_err("[ERROR] sii9234: Err RSEN_HIGH without RGND_1K rgnd=%d\n",
  2368. sii9234->rgnd);
  2369. goto err_exit2;
  2370. }
  2371. ret = mhl_tx_read_reg(sii9234, MHL_TX_SYSSTAT_REG, &value);
  2372. if (ret < 0) {
  2373. pr_err("[ERROR] sii9234: MHL_TX_SYSSTAT_REG read error\n");
  2374. goto err_exit2;
  2375. }
  2376. sii9234->rsen = value & RSEN_STATUS;
  2377. if (value & RSEN_STATUS) {
  2378. pr_info("%s(): MHL cable connected.. RSEN High\n",
  2379. __func__);
  2380. } else {
  2381. pr_info("%s(): RSEN lost -\n", __func__);
  2382. /* Once RSEN loss is confirmed,we need to check
  2383. * based on cable status and chip power status,whether
  2384. * it is SINK Loss(HDMI cable not connected, TV Off)
  2385. * or MHL cable disconnection
  2386. * TODO: Define the below mhl_disconnection()
  2387. */
  2388. #ifdef __CONFIG_USE_TIMER__
  2389. del_timer(&sii9234->cbus_command_timer);
  2390. #endif
  2391. msleep(T_SRC_RXSENSE_DEGLITCH);
  2392. ret = mhl_tx_read_reg(sii9234, MHL_TX_SYSSTAT_REG,
  2393. &value);
  2394. if (ret < 0) {
  2395. printk(KERN_ERR
  2396. "[ERROR] %s() read MHL_TX_SYSSTAT_REG\n",
  2397. __func__);
  2398. goto i2c_error_exit;
  2399. }
  2400. pr_cont(" sys_stat: %x\n", value);
  2401. if ((value & RSEN_STATUS) == 0) {
  2402. printk(KERN_INFO
  2403. "%s() RSEN Really LOW ~\n", __func__);
  2404. /*To meet CTS 3.3.22.2 spec*/
  2405. sii9234_tmds_control(sii9234, false);
  2406. force_usb_id_switch_open(sii9234);
  2407. release_usb_id_switch_open(sii9234);
  2408. mhl_poweroff = 1; /*Power down mhl chip */
  2409. goto err_exit;
  2410. } else
  2411. pr_info("sii9234: RSEN recovery ~\n");
  2412. }
  2413. }
  2414. /*
  2415. * Process CBUS interrupts only when MHL connection has been
  2416. * established
  2417. */
  2418. if (sii9234->state == STATE_ESTABLISHED) {
  2419. if (cbus_intr1 & MSC_RESP_ABORT)
  2420. cbus_resp_abort_error(sii9234);
  2421. if (cbus_intr1 & MSC_REQ_ABORT) {
  2422. #ifdef __CONFIG_USE_TIMER__
  2423. cbus_write_reg(sii9234,
  2424. CBUS_INTR1_ENABLE_REG, 0);
  2425. cbus_req_abort_error(sii9234);
  2426. cbus_write_reg(sii9234, CBUS_INTR1_ENABLE_REG, 0xFF);
  2427. cbus_command_abort_state = 1;
  2428. #else
  2429. cbus_req_abort_error(sii9234);
  2430. #endif
  2431. }
  2432. if ((cbus_intr1 & CBUS_DDC_ABORT) ||
  2433. (cbus_intr1 & MSC_RESP_ABORT)) {
  2434. pr_debug("sii9234: CBUS DDC abort\n");
  2435. if (cbus_ddc_abort_error(sii9234)) {
  2436. if (sii9234->claimed == true)
  2437. release_otg = true;
  2438. sii9234_power_down(sii9234);
  2439. }
  2440. }
  2441. if (cbus_intr1 & MSC_REQ_DONE) {
  2442. pr_debug("sii9234: CBUS cmd ACK Received\n");
  2443. #ifndef CONFIG_MHL_NEW_CBUS_MSC_CMD
  2444. cbus_resp_callback = cbus_command_response_all;
  2445. #else
  2446. complete(&sii9234->msc_complete);
  2447. #endif
  2448. }
  2449. #ifdef CONFIG_SII9234_RCP
  2450. if (cbus_intr1 & MSC_MSG_RECD) {
  2451. pr_debug("sii9234: MSC MSG Received\n");
  2452. cbus_handle_msc_msg(sii9234);
  2453. }
  2454. #endif
  2455. /* ignore WRT_STAT_RECD interrupt when we get HPD CHANGE */
  2456. if (cbus_intr2 & WRT_STAT_RECD && intr1 == 0)
  2457. cbus_handle_wrt_stat_recd(sii9234);
  2458. if (cbus_intr2 & SET_INT_RECD)
  2459. cbus_handle_set_int_recd(sii9234);
  2460. }
  2461. err_exit:
  2462. pr_debug("sii9234: wake_up\n");
  2463. wake_up(&sii9234->wq);
  2464. err_exit2:
  2465. ret = mhl_tx_write_reg(sii9234, MHL_TX_INTR1_REG, intr1);
  2466. if (ret < 0)
  2467. goto i2c_error_exit;
  2468. ret = mhl_tx_write_reg(sii9234, MHL_TX_INTR4_REG, intr4);
  2469. if (ret < 0)
  2470. goto i2c_error_exit;
  2471. ret = cbus_write_reg(sii9234, CBUS_INT_STATUS_1_REG, cbus_intr1);
  2472. if (ret < 0)
  2473. goto i2c_error_exit;
  2474. ret = cbus_write_reg(sii9234, CBUS_INT_STATUS_2_REG, cbus_intr2);
  2475. if (ret < 0)
  2476. goto i2c_error_exit;
  2477. sii9234_mutex_unlock(&sii9234->lock);
  2478. if (cbus_resp_callback)
  2479. cbus_resp_callback(sii9234);
  2480. if (mhl_poweroff) {
  2481. #ifdef CONFIG_MHL_D3_SUPPORT
  2482. if (sii9234_callback_sched != 0) {
  2483. sii9234_disable_irq();
  2484. goto_d3(NULL);
  2485. }
  2486. #else
  2487. mhl_onoff_ex(0);
  2488. #endif
  2489. }
  2490. return IRQ_HANDLED;
  2491. i2c_error_exit:
  2492. sii9234_mutex_unlock(&sii9234->lock);
  2493. pr_info("%s(): i2c error exit\n", __func__);
  2494. pr_debug("sii9234: wake_up\n");
  2495. wake_up(&sii9234->wq);
  2496. return IRQ_HANDLED;
  2497. }
  2498. static void mhl_cbus_command_timer(unsigned long data)
  2499. {
  2500. struct sii9234_data *sii9234 = dev_get_drvdata(sii9244_mhldev);
  2501. schedule_work(&sii9234->mhl_cbus_write_stat_work);
  2502. }
  2503. #ifdef MHL_SS_FACTORY
  2504. #define SII_ID 0x92
  2505. static ssize_t sysfs_check_mhl_command(struct class *class,
  2506. struct class_attribute *attr, char *buf)
  2507. {
  2508. int size;
  2509. u8 sii_id = 0;
  2510. struct sii9234_data *sii9234 = dev_get_drvdata(sii9244_mhldev);
  2511. if (sii9234->pdata->hw_onoff)
  2512. sii9234->pdata->hw_onoff(1);
  2513. if (sii9234->pdata->hw_reset)
  2514. sii9234->pdata->hw_reset();
  2515. mhl_tx_read_reg(sii9234, MHL_TX_IDH_REG, &sii_id);
  2516. pr_info("sel_show sii_id: %X\n", sii_id);
  2517. if (sii9234->pdata->hw_onoff)
  2518. sii9234->pdata->hw_onoff(0);
  2519. size = snprintf(buf, 10, "%d\n", sii_id == SII_ID ? 1 : 0);
  2520. return size;
  2521. }
  2522. static CLASS_ATTR(test_result, 0664 , sysfs_check_mhl_command, NULL);
  2523. #endif /*MHL_SS_FACTORY*/
  2524. #ifdef CONFIG_PM
  2525. static int sii9234_mhl_tx_suspend(struct device *dev)
  2526. {
  2527. struct sii9234_data *sii9234 = dev_get_drvdata(dev);
  2528. /*set config_gpio for mhl*/
  2529. if (sii9234->pdata->gpio_cfg)
  2530. sii9234->pdata->gpio_cfg();
  2531. return 0;
  2532. }
  2533. static int sii9234_mhl_tx_resume(struct device *dev)
  2534. {
  2535. struct sii9234_data *sii9234 = dev_get_drvdata(dev);
  2536. /*set config_gpio for mhl*/
  2537. if (sii9234->pdata->gpio_cfg)
  2538. sii9234->pdata->gpio_cfg();
  2539. return 0;
  2540. }
  2541. static const struct dev_pm_ops sii9234_pm_ops = {
  2542. .suspend = sii9234_mhl_tx_suspend,
  2543. .resume = sii9234_mhl_tx_resume,
  2544. };
  2545. #endif
  2546. static int __devinit sii9234_mhl_tx_i2c_probe(struct i2c_client *client,
  2547. const struct i2c_device_id *id)
  2548. {
  2549. struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
  2550. struct sii9234_data *sii9234;
  2551. #ifdef CONFIG_SII9234_RCP
  2552. struct input_dev *input;
  2553. #endif
  2554. int ret;
  2555. if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
  2556. return -EIO;
  2557. sii9234 = kzalloc(sizeof(struct sii9234_data), GFP_KERNEL);
  2558. if (!sii9234) {
  2559. dev_err(&client->dev, "failed to allocate driver data\n");
  2560. return -ENOMEM;
  2561. }
  2562. #ifdef CONFIG_SII9234_RCP
  2563. input = input_allocate_device();
  2564. if (!input) {
  2565. dev_err(&client->dev, "failed to allocate input device.\n");
  2566. ret = -ENOMEM;
  2567. goto err_exit0;
  2568. }
  2569. #endif
  2570. sii9234->pdata = client->dev.platform_data;
  2571. if (!sii9234->pdata) {
  2572. ret = -EINVAL;
  2573. goto err_exit1;
  2574. }
  2575. sii9234->pdata->mhl_tx_client = client;
  2576. init_waitqueue_head(&sii9234->wq);
  2577. mutex_init(&sii9234->lock);
  2578. mutex_init(&sii9234->cbus_lock);
  2579. INIT_WORK(&sii9234->mhl_cbus_write_stat_work,
  2580. mhl_cbus_write_stat_worker);
  2581. INIT_WORK(&sii9234->redetect_work,
  2582. sii9234_detection_callback);
  2583. i2c_set_clientdata(client, sii9234);
  2584. /* client->irq = sii9234->pdata->get_irq(); */
  2585. client->irq = gpio_to_irq(31);
  2586. printk(KERN_ERR "%s: mhl : gpio_to_irq : %d\n", __func__, client->irq);
  2587. sii9244_mhldev = &client->dev;
  2588. ret = request_threaded_irq(client->irq, NULL, sii9234_irq_thread,
  2589. IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
  2590. "sii9234", sii9234);
  2591. if (ret < 0)
  2592. goto err_exit1;
  2593. atomic_set(&sii9234->is_irq_enabled, false);
  2594. disable_irq(client->irq);
  2595. if (sii9234->pdata->swing_level == 0)
  2596. sii9234->pdata->swing_level = 0xEB;
  2597. #ifdef CONFIG_MHL_NEW_CBUS_MSC_CMD
  2598. sii9234_msc_wq = create_singlethread_workqueue("sii9234_msc_wq");
  2599. if (!sii9234_msc_wq) {
  2600. printk(KERN_ERR
  2601. "[ERROR] %s() workqueue create fail\n", __func__);
  2602. ret = -ENOMEM;
  2603. goto err_class;
  2604. }
  2605. INIT_WORK(&sii9234->msc_work, sii9234_process_msc_work);
  2606. #endif
  2607. #ifdef MHL_SS_FACTORY
  2608. pr_info("create mhl sysfile\n");
  2609. sec_mhl = class_create(THIS_MODULE, "mhl");
  2610. if (IS_ERR(sec_mhl)) {
  2611. pr_err("Failed to create class(sec_mhl)!\n");
  2612. goto err_class;
  2613. }
  2614. ret = class_create_file(sec_mhl, &class_attr_test_result);
  2615. if (ret) {
  2616. pr_err("[ERROR] Failed to create device file in sysfs entries!\n");
  2617. goto err_exit2a;
  2618. }
  2619. #endif
  2620. #ifdef CONFIG_MHL_SWING_LEVEL
  2621. pr_info("create mhl sysfile\n");
  2622. ret = class_create_file(sec_mhl, &class_attr_swing);
  2623. if (ret) {
  2624. pr_err("[ERROR] failed to create swing sysfs file\n");
  2625. goto err_exit2b;
  2626. }
  2627. #endif
  2628. sii9234->cbus_pkt.command = CBUS_IDLE;
  2629. sii9234->cbus_pkt.offset = DEVCAP_DEV_STATE;
  2630. init_timer(&sii9234->cbus_command_timer);
  2631. sii9234->cbus_command_timer.function =
  2632. mhl_cbus_command_timer;
  2633. sii9234->cbus_command_timer.data = (unsigned int)NULL;
  2634. sii9234->cbus_command_timer.expires = 0xffffffffL;
  2635. add_timer(&sii9234->cbus_command_timer);
  2636. #ifdef CONFIG_SII9234_RCP
  2637. /* indicate that we generate key events */
  2638. set_bit(EV_KEY, input->evbit);
  2639. bitmap_fill(input->keybit, KEY_MAX);
  2640. sii9234->input_dev = input;
  2641. input_set_drvdata(input, sii9234);
  2642. input->name = "sii9234_rcp";
  2643. input->id.bustype = BUS_I2C;
  2644. ret = input_register_device(input);
  2645. if (ret < 0) {
  2646. dev_err(&client->dev, "fail to register input device\n");
  2647. goto err_exit2c;
  2648. }
  2649. #endif
  2650. return 0;
  2651. err_exit2c:
  2652. #ifdef CONFIG_MHL_SWING_LEVEL
  2653. class_remove_file(sec_mhl, &class_attr_swing);
  2654. #endif
  2655. #ifdef CONFIG_MHL_SWING_LEVEL
  2656. err_exit2b:
  2657. #ifdef MHL_SS_FACTORY
  2658. class_destroy(sec_mhl);
  2659. #endif
  2660. #endif
  2661. err_exit2a:
  2662. #if defined(MHL_SS_FACTORY) || defined(CONFIG_MHL_SWING_LEVEL)
  2663. class_destroy(sec_mhl);
  2664. #endif
  2665. err_class:
  2666. free_irq(client->irq, sii9234);
  2667. err_exit1:
  2668. #ifdef CONFIG_SII9234_RCP
  2669. input_free_device(input);
  2670. #endif
  2671. err_exit0:
  2672. kfree(sii9234);
  2673. return ret;
  2674. }
  2675. static int __devinit sii9234_tpi_i2c_probe(struct i2c_client *client,
  2676. const struct i2c_device_id *id)
  2677. {
  2678. struct sii9234_platform_data *pdata = client->dev.platform_data;
  2679. if (!pdata)
  2680. return -EINVAL;
  2681. pdata->tpi_client = client;
  2682. return 0;
  2683. }
  2684. static int __devinit sii9234_hdmi_rx_i2c_probe(struct i2c_client *client,
  2685. const struct i2c_device_id *id)
  2686. {
  2687. struct sii9234_platform_data *pdata = client->dev.platform_data;
  2688. if (!pdata)
  2689. return -EINVAL;
  2690. pdata->hdmi_rx_client = client;
  2691. return 0;
  2692. }
  2693. static int __devinit sii9234_cbus_i2c_probe(struct i2c_client *client,
  2694. const struct i2c_device_id *id)
  2695. {
  2696. struct sii9234_platform_data *pdata = client->dev.platform_data;
  2697. if (!pdata)
  2698. return -EINVAL;
  2699. pdata->cbus_client = client;
  2700. return 0;
  2701. }
  2702. static int __devexit sii9234_mhl_tx_remove(struct i2c_client *client)
  2703. {
  2704. return 0;
  2705. }
  2706. static int __devexit sii9234_tpi_remove(struct i2c_client *client)
  2707. {
  2708. return 0;
  2709. }
  2710. static int __devexit sii9234_hdmi_rx_remove(struct i2c_client *client)
  2711. {
  2712. return 0;
  2713. }
  2714. static int __devexit sii9234_cbus_remove(struct i2c_client *client)
  2715. {
  2716. return 0;
  2717. }
  2718. static const struct i2c_device_id sii9234_mhl_tx_id[] = {
  2719. {"sii9234_mhl_tx", 0},
  2720. {}
  2721. };
  2722. static const struct i2c_device_id sii9234_tpi_id[] = {
  2723. {"sii9234_tpi", 0},
  2724. {}
  2725. };
  2726. static const struct i2c_device_id sii9234_hdmi_rx_id[] = {
  2727. {"sii9234_hdmi_rx", 0},
  2728. {}
  2729. };
  2730. static const struct i2c_device_id sii9234_cbus_id[] = {
  2731. {"sii9234_cbus", 0},
  2732. {}
  2733. };
  2734. MODULE_DEVICE_TABLE(i2c, sii9234_mhl_tx_id);
  2735. MODULE_DEVICE_TABLE(i2c, sii9234_tpi_id);
  2736. MODULE_DEVICE_TABLE(i2c, sii9234_hdmi_rx_id);
  2737. MODULE_DEVICE_TABLE(i2c, sii9234_cbus_id);
  2738. static struct i2c_driver sii9234_mhl_tx_i2c_driver = {
  2739. .driver = {
  2740. .owner = THIS_MODULE,
  2741. .name = "sii9234_mhl_tx",
  2742. #ifdef CONFIG_PM
  2743. .pm = &sii9234_pm_ops,
  2744. #endif
  2745. },
  2746. .id_table = sii9234_mhl_tx_id,
  2747. .probe = sii9234_mhl_tx_i2c_probe,
  2748. .remove = __devexit_p(sii9234_mhl_tx_remove),
  2749. .command = NULL,
  2750. };
  2751. static struct i2c_driver sii9234_tpi_i2c_driver = {
  2752. .driver = {
  2753. .owner = THIS_MODULE,
  2754. .name = "sii9234_tpi",
  2755. },
  2756. .id_table = sii9234_tpi_id,
  2757. .probe = sii9234_tpi_i2c_probe,
  2758. .remove = __devexit_p(sii9234_tpi_remove),
  2759. };
  2760. static struct i2c_driver sii9234_hdmi_rx_i2c_driver = {
  2761. .driver = {
  2762. .owner = THIS_MODULE,
  2763. .name = "sii9234_hdmi_rx",
  2764. },
  2765. .id_table = sii9234_hdmi_rx_id,
  2766. .probe = sii9234_hdmi_rx_i2c_probe,
  2767. .remove = __devexit_p(sii9234_hdmi_rx_remove),
  2768. };
  2769. static struct i2c_driver sii9234_cbus_i2c_driver = {
  2770. .driver = {
  2771. .owner = THIS_MODULE,
  2772. .name = "sii9234_cbus",
  2773. },
  2774. .id_table = sii9234_cbus_id,
  2775. .probe = sii9234_cbus_i2c_probe,
  2776. .remove = __devexit_p(sii9234_cbus_remove),
  2777. };
  2778. static int __init sii9234_init(void)
  2779. {
  2780. int ret;
  2781. ret = i2c_add_driver(&sii9234_mhl_tx_i2c_driver);
  2782. if (ret < 0)
  2783. return ret;
  2784. ret = i2c_add_driver(&sii9234_tpi_i2c_driver);
  2785. if (ret < 0)
  2786. goto err_exit1;
  2787. ret = i2c_add_driver(&sii9234_hdmi_rx_i2c_driver);
  2788. if (ret < 0)
  2789. goto err_exit2;
  2790. ret = i2c_add_driver(&sii9234_cbus_i2c_driver);
  2791. if (ret < 0)
  2792. goto err_exit3;
  2793. return 0;
  2794. err_exit3:
  2795. i2c_del_driver(&sii9234_hdmi_rx_i2c_driver);
  2796. err_exit2:
  2797. i2c_del_driver(&sii9234_tpi_i2c_driver);
  2798. err_exit1:
  2799. i2c_del_driver(&sii9234_mhl_tx_i2c_driver);
  2800. pr_err("i2c_add_driver fail\n");
  2801. return ret;
  2802. }
  2803. static void __exit sii9234_exit(void)
  2804. {
  2805. i2c_del_driver(&sii9234_cbus_i2c_driver);
  2806. i2c_del_driver(&sii9234_hdmi_rx_i2c_driver);
  2807. i2c_del_driver(&sii9234_tpi_i2c_driver);
  2808. i2c_del_driver(&sii9234_mhl_tx_i2c_driver);
  2809. }
  2810. module_init(sii9234_init);
  2811. module_exit(sii9234_exit);