video.c 48 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988
  1. /*
  2. * video.c - ACPI Video Driver ($Revision:$)
  3. *
  4. * Copyright (C) 2004 Luming Yu <luming.yu@intel.com>
  5. * Copyright (C) 2004 Bruno Ducrot <ducrot@poupinou.org>
  6. *
  7. * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation; either version 2 of the License, or (at
  12. * your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful, but
  15. * WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License along
  20. * with this program; if not, write to the Free Software Foundation, Inc.,
  21. * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  22. *
  23. * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  24. */
  25. #include <linux/kernel.h>
  26. #include <linux/module.h>
  27. #include <linux/init.h>
  28. #include <linux/types.h>
  29. #include <linux/list.h>
  30. #include <linux/proc_fs.h>
  31. #include <linux/seq_file.h>
  32. #include <asm/uaccess.h>
  33. #include <acpi/acpi_bus.h>
  34. #include <acpi/acpi_drivers.h>
  35. #define ACPI_VIDEO_COMPONENT 0x08000000
  36. #define ACPI_VIDEO_CLASS "video"
  37. #define ACPI_VIDEO_DRIVER_NAME "ACPI Video Driver"
  38. #define ACPI_VIDEO_BUS_NAME "Video Bus"
  39. #define ACPI_VIDEO_DEVICE_NAME "Video Device"
  40. #define ACPI_VIDEO_NOTIFY_SWITCH 0x80
  41. #define ACPI_VIDEO_NOTIFY_PROBE 0x81
  42. #define ACPI_VIDEO_NOTIFY_CYCLE 0x82
  43. #define ACPI_VIDEO_NOTIFY_NEXT_OUTPUT 0x83
  44. #define ACPI_VIDEO_NOTIFY_PREV_OUTPUT 0x84
  45. #define ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS 0x82
  46. #define ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS 0x83
  47. #define ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS 0x84
  48. #define ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS 0x85
  49. #define ACPI_VIDEO_NOTIFY_DISPLAY_OFF 0x86
  50. #define ACPI_VIDEO_HEAD_INVALID (~0u - 1)
  51. #define ACPI_VIDEO_HEAD_END (~0u)
  52. #define _COMPONENT ACPI_VIDEO_COMPONENT
  53. ACPI_MODULE_NAME ("acpi_video")
  54. MODULE_AUTHOR("Bruno Ducrot");
  55. MODULE_DESCRIPTION(ACPI_VIDEO_DRIVER_NAME);
  56. MODULE_LICENSE("GPL");
  57. static int acpi_video_bus_add (struct acpi_device *device);
  58. static int acpi_video_bus_remove (struct acpi_device *device, int type);
  59. static int acpi_video_bus_match (struct acpi_device *device, struct acpi_driver *driver);
  60. static struct acpi_driver acpi_video_bus = {
  61. .name = ACPI_VIDEO_DRIVER_NAME,
  62. .class = ACPI_VIDEO_CLASS,
  63. .ops = {
  64. .add = acpi_video_bus_add,
  65. .remove = acpi_video_bus_remove,
  66. .match = acpi_video_bus_match,
  67. },
  68. };
  69. struct acpi_video_bus_flags {
  70. u8 multihead:1; /* can switch video heads */
  71. u8 rom:1; /* can retrieve a video rom */
  72. u8 post:1; /* can configure the head to */
  73. u8 reserved:5;
  74. };
  75. struct acpi_video_bus_cap {
  76. u8 _DOS:1; /*Enable/Disable output switching*/
  77. u8 _DOD:1; /*Enumerate all devices attached to display adapter*/
  78. u8 _ROM:1; /*Get ROM Data*/
  79. u8 _GPD:1; /*Get POST Device*/
  80. u8 _SPD:1; /*Set POST Device*/
  81. u8 _VPO:1; /*Video POST Options*/
  82. u8 reserved:2;
  83. };
  84. struct acpi_video_device_attrib{
  85. u32 display_index:4; /* A zero-based instance of the Display*/
  86. u32 display_port_attachment:4; /*This field differenates displays type*/
  87. u32 display_type:4; /*Describe the specific type in use*/
  88. u32 vendor_specific:4; /*Chipset Vendor Specifi*/
  89. u32 bios_can_detect:1; /*BIOS can detect the device*/
  90. u32 depend_on_vga:1; /*Non-VGA output device whose power is related to
  91. the VGA device.*/
  92. u32 pipe_id:3; /*For VGA multiple-head devices.*/
  93. u32 reserved:10; /*Must be 0*/
  94. u32 device_id_scheme:1; /*Device ID Scheme*/
  95. };
  96. struct acpi_video_enumerated_device {
  97. union {
  98. u32 int_val;
  99. struct acpi_video_device_attrib attrib;
  100. } value;
  101. struct acpi_video_device *bind_info;
  102. };
  103. struct acpi_video_bus {
  104. acpi_handle handle;
  105. u8 dos_setting;
  106. struct acpi_video_enumerated_device *attached_array;
  107. u8 attached_count;
  108. struct acpi_video_bus_cap cap;
  109. struct acpi_video_bus_flags flags;
  110. struct semaphore sem;
  111. struct list_head video_device_list;
  112. struct proc_dir_entry *dir;
  113. };
  114. struct acpi_video_device_flags {
  115. u8 crt:1;
  116. u8 lcd:1;
  117. u8 tvout:1;
  118. u8 bios:1;
  119. u8 unknown:1;
  120. u8 reserved:3;
  121. };
  122. struct acpi_video_device_cap {
  123. u8 _ADR:1; /*Return the unique ID */
  124. u8 _BCL:1; /*Query list of brightness control levels supported*/
  125. u8 _BCM:1; /*Set the brightness level*/
  126. u8 _DDC:1; /*Return the EDID for this device*/
  127. u8 _DCS:1; /*Return status of output device*/
  128. u8 _DGS:1; /*Query graphics state*/
  129. u8 _DSS:1; /*Device state set*/
  130. u8 _reserved:1;
  131. };
  132. struct acpi_video_device_brightness {
  133. int curr;
  134. int count;
  135. int *levels;
  136. };
  137. struct acpi_video_device {
  138. acpi_handle handle;
  139. unsigned long device_id;
  140. struct acpi_video_device_flags flags;
  141. struct acpi_video_device_cap cap;
  142. struct list_head entry;
  143. struct acpi_video_bus *video;
  144. struct acpi_device *dev;
  145. struct acpi_video_device_brightness *brightness;
  146. };
  147. /* bus */
  148. static int acpi_video_bus_info_open_fs(struct inode *inode, struct file *file);
  149. static struct file_operations acpi_video_bus_info_fops = {
  150. .open = acpi_video_bus_info_open_fs,
  151. .read = seq_read,
  152. .llseek = seq_lseek,
  153. .release = single_release,
  154. };
  155. static int acpi_video_bus_ROM_open_fs(struct inode *inode, struct file *file);
  156. static struct file_operations acpi_video_bus_ROM_fops = {
  157. .open = acpi_video_bus_ROM_open_fs,
  158. .read = seq_read,
  159. .llseek = seq_lseek,
  160. .release = single_release,
  161. };
  162. static int acpi_video_bus_POST_info_open_fs(struct inode *inode, struct file *file);
  163. static struct file_operations acpi_video_bus_POST_info_fops = {
  164. .open = acpi_video_bus_POST_info_open_fs,
  165. .read = seq_read,
  166. .llseek = seq_lseek,
  167. .release = single_release,
  168. };
  169. static int acpi_video_bus_POST_open_fs(struct inode *inode, struct file *file);
  170. static struct file_operations acpi_video_bus_POST_fops = {
  171. .open = acpi_video_bus_POST_open_fs,
  172. .read = seq_read,
  173. .llseek = seq_lseek,
  174. .release = single_release,
  175. };
  176. static int acpi_video_bus_DOS_open_fs(struct inode *inode, struct file *file);
  177. static struct file_operations acpi_video_bus_DOS_fops = {
  178. .open = acpi_video_bus_DOS_open_fs,
  179. .read = seq_read,
  180. .llseek = seq_lseek,
  181. .release = single_release,
  182. };
  183. /* device */
  184. static int acpi_video_device_info_open_fs(struct inode *inode, struct file *file);
  185. static struct file_operations acpi_video_device_info_fops = {
  186. .open = acpi_video_device_info_open_fs,
  187. .read = seq_read,
  188. .llseek = seq_lseek,
  189. .release = single_release,
  190. };
  191. static int acpi_video_device_state_open_fs(struct inode *inode, struct file *file);
  192. static struct file_operations acpi_video_device_state_fops = {
  193. .open = acpi_video_device_state_open_fs,
  194. .read = seq_read,
  195. .llseek = seq_lseek,
  196. .release = single_release,
  197. };
  198. static int acpi_video_device_brightness_open_fs(struct inode *inode, struct file *file);
  199. static struct file_operations acpi_video_device_brightness_fops = {
  200. .open = acpi_video_device_brightness_open_fs,
  201. .read = seq_read,
  202. .llseek = seq_lseek,
  203. .release = single_release,
  204. };
  205. static int acpi_video_device_EDID_open_fs(struct inode *inode, struct file *file);
  206. static struct file_operations acpi_video_device_EDID_fops = {
  207. .open = acpi_video_device_EDID_open_fs,
  208. .read = seq_read,
  209. .llseek = seq_lseek,
  210. .release = single_release,
  211. };
  212. static char device_decode[][30] = {
  213. "motherboard VGA device",
  214. "PCI VGA device",
  215. "AGP VGA device",
  216. "UNKNOWN",
  217. };
  218. static void acpi_video_device_notify ( acpi_handle handle, u32 event, void *data);
  219. static void acpi_video_device_rebind( struct acpi_video_bus *video);
  220. static void acpi_video_device_bind( struct acpi_video_bus *video, struct acpi_video_device *device);
  221. static int acpi_video_device_enumerate(struct acpi_video_bus *video);
  222. static int acpi_video_switch_output( struct acpi_video_bus *video, int event);
  223. static int acpi_video_get_next_level( struct acpi_video_device *device, u32 level_current,u32 event);
  224. static void acpi_video_switch_brightness ( struct acpi_video_device *device, int event);
  225. /* --------------------------------------------------------------------------
  226. Video Management
  227. -------------------------------------------------------------------------- */
  228. /* device */
  229. static int
  230. acpi_video_device_query (
  231. struct acpi_video_device *device,
  232. unsigned long *state)
  233. {
  234. int status;
  235. ACPI_FUNCTION_TRACE("acpi_video_device_query");
  236. status = acpi_evaluate_integer(device->handle, "_DGS", NULL, state);
  237. return_VALUE(status);
  238. }
  239. static int
  240. acpi_video_device_get_state (
  241. struct acpi_video_device *device,
  242. unsigned long *state)
  243. {
  244. int status;
  245. ACPI_FUNCTION_TRACE("acpi_video_device_get_state");
  246. status = acpi_evaluate_integer(device->handle, "_DCS", NULL, state);
  247. return_VALUE(status);
  248. }
  249. static int
  250. acpi_video_device_set_state (
  251. struct acpi_video_device *device,
  252. int state)
  253. {
  254. int status;
  255. union acpi_object arg0 = {ACPI_TYPE_INTEGER};
  256. struct acpi_object_list args = {1, &arg0};
  257. ACPI_FUNCTION_TRACE("acpi_video_device_set_state");
  258. arg0.integer.value = state;
  259. status = acpi_evaluate_integer(device->handle, "_DSS", &args, NULL);
  260. return_VALUE(status);
  261. }
  262. static int
  263. acpi_video_device_lcd_query_levels (
  264. struct acpi_video_device *device,
  265. union acpi_object **levels)
  266. {
  267. int status;
  268. struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
  269. union acpi_object *obj;
  270. ACPI_FUNCTION_TRACE("acpi_video_device_lcd_query_levels");
  271. *levels = NULL;
  272. status = acpi_evaluate_object(device->handle, "_BCL", NULL, &buffer);
  273. if (!ACPI_SUCCESS(status))
  274. return_VALUE(status);
  275. obj = (union acpi_object *) buffer.pointer;
  276. if (!obj && (obj->type != ACPI_TYPE_PACKAGE)) {
  277. ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _BCL data\n"));
  278. status = -EFAULT;
  279. goto err;
  280. }
  281. *levels = obj;
  282. return_VALUE(0);
  283. err:
  284. if (buffer.pointer)
  285. kfree(buffer.pointer);
  286. return_VALUE(status);
  287. }
  288. static int
  289. acpi_video_device_lcd_set_level (
  290. struct acpi_video_device *device,
  291. int level)
  292. {
  293. int status;
  294. union acpi_object arg0 = {ACPI_TYPE_INTEGER};
  295. struct acpi_object_list args = {1, &arg0};
  296. ACPI_FUNCTION_TRACE("acpi_video_device_lcd_set_level");
  297. arg0.integer.value = level;
  298. status = acpi_evaluate_object(device->handle, "_BCM", &args, NULL);
  299. printk(KERN_DEBUG "set_level status: %x\n", status);
  300. return_VALUE(status);
  301. }
  302. static int
  303. acpi_video_device_lcd_get_level_current (
  304. struct acpi_video_device *device,
  305. unsigned long *level)
  306. {
  307. int status;
  308. ACPI_FUNCTION_TRACE("acpi_video_device_lcd_get_level_current");
  309. status = acpi_evaluate_integer(device->handle, "_BQC", NULL, level);
  310. return_VALUE(status);
  311. }
  312. static int
  313. acpi_video_device_EDID (
  314. struct acpi_video_device *device,
  315. union acpi_object **edid,
  316. ssize_t length)
  317. {
  318. int status;
  319. struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
  320. union acpi_object *obj;
  321. union acpi_object arg0 = {ACPI_TYPE_INTEGER};
  322. struct acpi_object_list args = {1, &arg0};
  323. ACPI_FUNCTION_TRACE("acpi_video_device_get_EDID");
  324. *edid = NULL;
  325. if (!device)
  326. return_VALUE(-ENODEV);
  327. if (length == 128)
  328. arg0.integer.value = 1;
  329. else if (length == 256)
  330. arg0.integer.value = 2;
  331. else
  332. return_VALUE(-EINVAL);
  333. status = acpi_evaluate_object(device->handle, "_DDC", &args, &buffer);
  334. if (ACPI_FAILURE(status))
  335. return_VALUE(-ENODEV);
  336. obj = (union acpi_object *) buffer.pointer;
  337. if (obj && obj->type == ACPI_TYPE_BUFFER)
  338. *edid = obj;
  339. else {
  340. ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _DDC data\n"));
  341. status = -EFAULT;
  342. kfree(obj);
  343. }
  344. return_VALUE(status);
  345. }
  346. /* bus */
  347. static int
  348. acpi_video_bus_set_POST (
  349. struct acpi_video_bus *video,
  350. unsigned long option)
  351. {
  352. int status;
  353. unsigned long tmp;
  354. union acpi_object arg0 = {ACPI_TYPE_INTEGER};
  355. struct acpi_object_list args = {1, &arg0};
  356. ACPI_FUNCTION_TRACE("acpi_video_bus_set_POST");
  357. arg0.integer.value = option;
  358. status = acpi_evaluate_integer(video->handle, "_SPD", &args, &tmp);
  359. if (ACPI_SUCCESS(status))
  360. status = tmp ? (-EINVAL):(AE_OK);
  361. return_VALUE(status);
  362. }
  363. static int
  364. acpi_video_bus_get_POST (
  365. struct acpi_video_bus *video,
  366. unsigned long *id)
  367. {
  368. int status;
  369. ACPI_FUNCTION_TRACE("acpi_video_bus_get_POST");
  370. status = acpi_evaluate_integer(video->handle, "_GPD", NULL, id);
  371. return_VALUE(status);
  372. }
  373. static int
  374. acpi_video_bus_POST_options (
  375. struct acpi_video_bus *video,
  376. unsigned long *options)
  377. {
  378. int status;
  379. ACPI_FUNCTION_TRACE("acpi_video_bus_POST_options");
  380. status = acpi_evaluate_integer(video->handle, "_VPO", NULL, options);
  381. *options &= 3;
  382. return_VALUE(status);
  383. }
  384. /*
  385. * Arg:
  386. * video : video bus device pointer
  387. * bios_flag :
  388. * 0. The system BIOS should NOT automatically switch(toggle)
  389. * the active display output.
  390. * 1. The system BIOS should automatically switch (toggle) the
  391. * active display output. No swich event.
  392. * 2. The _DGS value should be locked.
  393. * 3. The system BIOS should not automatically switch (toggle) the
  394. * active display output, but instead generate the display switch
  395. * event notify code.
  396. * lcd_flag :
  397. * 0. The system BIOS should automatically control the brightness level
  398. * of the LCD, when the power changes from AC to DC
  399. * 1. The system BIOS should NOT automatically control the brightness
  400. * level of the LCD, when the power changes from AC to DC.
  401. * Return Value:
  402. * -1 wrong arg.
  403. */
  404. static int
  405. acpi_video_bus_DOS(
  406. struct acpi_video_bus *video,
  407. int bios_flag,
  408. int lcd_flag)
  409. {
  410. acpi_integer status = 0;
  411. union acpi_object arg0 = {ACPI_TYPE_INTEGER};
  412. struct acpi_object_list args = {1, &arg0};
  413. ACPI_FUNCTION_TRACE("acpi_video_bus_DOS");
  414. if (bios_flag < 0 || bios_flag >3 || lcd_flag < 0 || lcd_flag > 1){
  415. status = -1;
  416. goto Failed;
  417. }
  418. arg0.integer.value = (lcd_flag << 2) | bios_flag;
  419. video->dos_setting = arg0.integer.value;
  420. acpi_evaluate_object(video->handle, "_DOS", &args, NULL);
  421. Failed:
  422. return_VALUE(status);
  423. }
  424. /*
  425. * Arg:
  426. * device : video output device (LCD, CRT, ..)
  427. *
  428. * Return Value:
  429. * None
  430. *
  431. * Find out all required AML method defined under the output
  432. * device.
  433. */
  434. static void
  435. acpi_video_device_find_cap (struct acpi_video_device *device)
  436. {
  437. acpi_integer status;
  438. acpi_handle h_dummy1;
  439. int i;
  440. union acpi_object *obj = NULL;
  441. struct acpi_video_device_brightness *br = NULL;
  442. ACPI_FUNCTION_TRACE("acpi_video_device_find_cap");
  443. memset( &device->cap, 0, 4);
  444. if( ACPI_SUCCESS(acpi_get_handle(device->handle, "_ADR", &h_dummy1))) {
  445. device->cap._ADR = 1;
  446. }
  447. if( ACPI_SUCCESS(acpi_get_handle(device->handle, "_BCL", &h_dummy1))) {
  448. device->cap._BCL= 1;
  449. }
  450. if( ACPI_SUCCESS(acpi_get_handle(device->handle, "_BCM", &h_dummy1))) {
  451. device->cap._BCM= 1;
  452. }
  453. if( ACPI_SUCCESS(acpi_get_handle(device->handle, "_DDC", &h_dummy1))) {
  454. device->cap._DDC= 1;
  455. }
  456. if( ACPI_SUCCESS(acpi_get_handle(device->handle, "_DCS", &h_dummy1))) {
  457. device->cap._DCS = 1;
  458. }
  459. if( ACPI_SUCCESS(acpi_get_handle(device->handle, "_DGS", &h_dummy1))) {
  460. device->cap._DGS = 1;
  461. }
  462. if( ACPI_SUCCESS(acpi_get_handle(device->handle, "_DSS", &h_dummy1))) {
  463. device->cap._DSS = 1;
  464. }
  465. status = acpi_video_device_lcd_query_levels(device, &obj);
  466. if (obj && obj->type == ACPI_TYPE_PACKAGE && obj->package.count >= 2) {
  467. int count = 0;
  468. union acpi_object *o;
  469. br = kmalloc(sizeof(*br), GFP_KERNEL);
  470. if (!br) {
  471. printk(KERN_ERR "can't allocate memory\n");
  472. } else {
  473. memset(br, 0, sizeof(*br));
  474. br->levels = kmalloc(obj->package.count *
  475. sizeof *(br->levels), GFP_KERNEL);
  476. if (!br->levels)
  477. goto out;
  478. for (i = 0; i < obj->package.count; i++) {
  479. o = (union acpi_object *) &obj->package.elements[i];
  480. if (o->type != ACPI_TYPE_INTEGER) {
  481. ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid data\n"));
  482. continue;
  483. }
  484. br->levels[count] = (u32) o->integer.value;
  485. count++;
  486. }
  487. out:
  488. if (count < 2) {
  489. kfree(br->levels);
  490. kfree(br);
  491. } else {
  492. br->count = count;
  493. device->brightness = br;
  494. ACPI_DEBUG_PRINT((ACPI_DB_INFO, "found %d brightness levels\n", count));
  495. }
  496. }
  497. }
  498. kfree(obj);
  499. return_VOID;
  500. }
  501. /*
  502. * Arg:
  503. * device : video output device (VGA)
  504. *
  505. * Return Value:
  506. * None
  507. *
  508. * Find out all required AML method defined under the video bus device.
  509. */
  510. static void
  511. acpi_video_bus_find_cap (struct acpi_video_bus *video)
  512. {
  513. acpi_handle h_dummy1;
  514. memset(&video->cap ,0, 4);
  515. if( ACPI_SUCCESS(acpi_get_handle(video->handle, "_DOS", &h_dummy1))) {
  516. video->cap._DOS = 1;
  517. }
  518. if( ACPI_SUCCESS(acpi_get_handle(video->handle, "_DOD", &h_dummy1))) {
  519. video->cap._DOD = 1;
  520. }
  521. if( ACPI_SUCCESS(acpi_get_handle(video->handle, "_ROM", &h_dummy1))) {
  522. video->cap._ROM = 1;
  523. }
  524. if( ACPI_SUCCESS(acpi_get_handle(video->handle, "_GPD", &h_dummy1))) {
  525. video->cap._GPD = 1;
  526. }
  527. if( ACPI_SUCCESS(acpi_get_handle(video->handle, "_SPD", &h_dummy1))) {
  528. video->cap._SPD = 1;
  529. }
  530. if( ACPI_SUCCESS(acpi_get_handle(video->handle, "_VPO", &h_dummy1))) {
  531. video->cap._VPO = 1;
  532. }
  533. }
  534. /*
  535. * Check whether the video bus device has required AML method to
  536. * support the desired features
  537. */
  538. static int
  539. acpi_video_bus_check (
  540. struct acpi_video_bus *video)
  541. {
  542. acpi_status status = -ENOENT;
  543. ACPI_FUNCTION_TRACE("acpi_video_bus_check");
  544. if (!video)
  545. return_VALUE(-EINVAL);
  546. /* Since there is no HID, CID and so on for VGA driver, we have
  547. * to check well known required nodes.
  548. */
  549. /* Does this device able to support video switching ? */
  550. if(video->cap._DOS){
  551. video->flags.multihead = 1;
  552. status = 0;
  553. }
  554. /* Does this device able to retrieve a retrieve a video ROM ? */
  555. if(video->cap._ROM){
  556. video->flags.rom = 1;
  557. status = 0;
  558. }
  559. /* Does this device able to configure which video device to POST ? */
  560. if(video->cap._GPD && video->cap._SPD && video->cap._VPO){
  561. video->flags.post = 1;
  562. status = 0;
  563. }
  564. return_VALUE(status);
  565. }
  566. /* --------------------------------------------------------------------------
  567. FS Interface (/proc)
  568. -------------------------------------------------------------------------- */
  569. static struct proc_dir_entry *acpi_video_dir;
  570. /* video devices */
  571. static int
  572. acpi_video_device_info_seq_show (
  573. struct seq_file *seq,
  574. void *offset)
  575. {
  576. struct acpi_video_device *dev = (struct acpi_video_device *) seq->private;
  577. ACPI_FUNCTION_TRACE("acpi_video_device_info_seq_show");
  578. if (!dev)
  579. goto end;
  580. seq_printf(seq, "device_id: 0x%04x\n", (u32) dev->device_id);
  581. seq_printf(seq, "type: ");
  582. if (dev->flags.crt)
  583. seq_printf(seq, "CRT\n");
  584. else if (dev->flags.lcd)
  585. seq_printf(seq, "LCD\n");
  586. else if (dev->flags.tvout)
  587. seq_printf(seq, "TVOUT\n");
  588. else
  589. seq_printf(seq, "UNKNOWN\n");
  590. seq_printf(seq,"known by bios: %s\n",
  591. dev->flags.bios ? "yes":"no");
  592. end:
  593. return_VALUE(0);
  594. }
  595. static int
  596. acpi_video_device_info_open_fs (
  597. struct inode *inode,
  598. struct file *file)
  599. {
  600. return single_open(file, acpi_video_device_info_seq_show,
  601. PDE(inode)->data);
  602. }
  603. static int
  604. acpi_video_device_state_seq_show (
  605. struct seq_file *seq,
  606. void *offset)
  607. {
  608. int status;
  609. struct acpi_video_device *dev = (struct acpi_video_device *) seq->private;
  610. unsigned long state;
  611. ACPI_FUNCTION_TRACE("acpi_video_device_state_seq_show");
  612. if (!dev)
  613. goto end;
  614. status = acpi_video_device_get_state(dev, &state);
  615. seq_printf(seq, "state: ");
  616. if (ACPI_SUCCESS(status))
  617. seq_printf(seq, "0x%02lx\n", state);
  618. else
  619. seq_printf(seq, "<not supported>\n");
  620. status = acpi_video_device_query(dev, &state);
  621. seq_printf(seq, "query: ");
  622. if (ACPI_SUCCESS(status))
  623. seq_printf(seq, "0x%02lx\n", state);
  624. else
  625. seq_printf(seq, "<not supported>\n");
  626. end:
  627. return_VALUE(0);
  628. }
  629. static int
  630. acpi_video_device_state_open_fs (
  631. struct inode *inode,
  632. struct file *file)
  633. {
  634. return single_open(file, acpi_video_device_state_seq_show,
  635. PDE(inode)->data);
  636. }
  637. static ssize_t
  638. acpi_video_device_write_state (
  639. struct file *file,
  640. const char __user *buffer,
  641. size_t count,
  642. loff_t *data)
  643. {
  644. int status;
  645. struct seq_file *m = (struct seq_file *) file->private_data;
  646. struct acpi_video_device *dev = (struct acpi_video_device *) m->private;
  647. char str[12] = {0};
  648. u32 state = 0;
  649. ACPI_FUNCTION_TRACE("acpi_video_device_write_state");
  650. if (!dev || count + 1 > sizeof str)
  651. return_VALUE(-EINVAL);
  652. if (copy_from_user(str, buffer, count))
  653. return_VALUE(-EFAULT);
  654. str[count] = 0;
  655. state = simple_strtoul(str, NULL, 0);
  656. state &= ((1ul<<31) | (1ul<<30) | (1ul<<0));
  657. status = acpi_video_device_set_state(dev, state);
  658. if (status)
  659. return_VALUE(-EFAULT);
  660. return_VALUE(count);
  661. }
  662. static int
  663. acpi_video_device_brightness_seq_show (
  664. struct seq_file *seq,
  665. void *offset)
  666. {
  667. struct acpi_video_device *dev = (struct acpi_video_device *) seq->private;
  668. int i;
  669. ACPI_FUNCTION_TRACE("acpi_video_device_brightness_seq_show");
  670. if (!dev || !dev->brightness) {
  671. seq_printf(seq, "<not supported>\n");
  672. return_VALUE(0);
  673. }
  674. seq_printf(seq, "levels: ");
  675. for (i = 0; i < dev->brightness->count; i++)
  676. seq_printf(seq, " %d", dev->brightness->levels[i]);
  677. seq_printf(seq, "\ncurrent: %d\n", dev->brightness->curr);
  678. return_VALUE(0);
  679. }
  680. static int
  681. acpi_video_device_brightness_open_fs (
  682. struct inode *inode,
  683. struct file *file)
  684. {
  685. return single_open(file, acpi_video_device_brightness_seq_show,
  686. PDE(inode)->data);
  687. }
  688. static ssize_t
  689. acpi_video_device_write_brightness (
  690. struct file *file,
  691. const char __user *buffer,
  692. size_t count,
  693. loff_t *data)
  694. {
  695. struct seq_file *m = (struct seq_file *) file->private_data;
  696. struct acpi_video_device *dev = (struct acpi_video_device *) m->private;
  697. char str[4] = {0};
  698. unsigned int level = 0;
  699. int i;
  700. ACPI_FUNCTION_TRACE("acpi_video_device_write_brightness");
  701. if (!dev || count + 1 > sizeof str)
  702. return_VALUE(-EINVAL);
  703. if (copy_from_user(str, buffer, count))
  704. return_VALUE(-EFAULT);
  705. str[count] = 0;
  706. level = simple_strtoul(str, NULL, 0);
  707. if (level > 100)
  708. return_VALUE(-EFAULT);
  709. /* validate though the list of available levels */
  710. for (i = 0; i < dev->brightness->count; i++)
  711. if (level == dev->brightness->levels[i]) {
  712. if (ACPI_SUCCESS(acpi_video_device_lcd_set_level(dev, level)))
  713. dev->brightness->curr = level;
  714. break;
  715. }
  716. return_VALUE(count);
  717. }
  718. static int
  719. acpi_video_device_EDID_seq_show (
  720. struct seq_file *seq,
  721. void *offset)
  722. {
  723. struct acpi_video_device *dev = (struct acpi_video_device *) seq->private;
  724. int status;
  725. int i;
  726. union acpi_object *edid = NULL;
  727. ACPI_FUNCTION_TRACE("acpi_video_device_EDID_seq_show");
  728. if (!dev)
  729. goto out;
  730. status = acpi_video_device_EDID (dev, &edid, 128);
  731. if (ACPI_FAILURE(status)) {
  732. status = acpi_video_device_EDID (dev, &edid, 256);
  733. }
  734. if (ACPI_FAILURE(status)) {
  735. goto out;
  736. }
  737. if (edid && edid->type == ACPI_TYPE_BUFFER) {
  738. for (i = 0; i < edid->buffer.length; i++)
  739. seq_putc(seq, edid->buffer.pointer[i]);
  740. }
  741. out:
  742. if (!edid)
  743. seq_printf(seq, "<not supported>\n");
  744. else
  745. kfree(edid);
  746. return_VALUE(0);
  747. }
  748. static int
  749. acpi_video_device_EDID_open_fs (
  750. struct inode *inode,
  751. struct file *file)
  752. {
  753. return single_open(file, acpi_video_device_EDID_seq_show,
  754. PDE(inode)->data);
  755. }
  756. static int
  757. acpi_video_device_add_fs (
  758. struct acpi_device *device)
  759. {
  760. struct proc_dir_entry *entry = NULL;
  761. struct acpi_video_device *vid_dev;
  762. ACPI_FUNCTION_TRACE("acpi_video_device_add_fs");
  763. if (!device)
  764. return_VALUE(-ENODEV);
  765. vid_dev = (struct acpi_video_device *) acpi_driver_data(device);
  766. if (!vid_dev)
  767. return_VALUE(-ENODEV);
  768. if (!acpi_device_dir(device)) {
  769. acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
  770. vid_dev->video->dir);
  771. if (!acpi_device_dir(device))
  772. return_VALUE(-ENODEV);
  773. acpi_device_dir(device)->owner = THIS_MODULE;
  774. }
  775. /* 'info' [R] */
  776. entry = create_proc_entry("info", S_IRUGO, acpi_device_dir(device));
  777. if (!entry)
  778. ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
  779. "Unable to create 'info' fs entry\n"));
  780. else {
  781. entry->proc_fops = &acpi_video_device_info_fops;
  782. entry->data = acpi_driver_data(device);
  783. entry->owner = THIS_MODULE;
  784. }
  785. /* 'state' [R/W] */
  786. entry = create_proc_entry("state", S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device));
  787. if (!entry)
  788. ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
  789. "Unable to create 'state' fs entry\n"));
  790. else {
  791. entry->proc_fops = &acpi_video_device_state_fops;
  792. entry->proc_fops->write = acpi_video_device_write_state;
  793. entry->data = acpi_driver_data(device);
  794. entry->owner = THIS_MODULE;
  795. }
  796. /* 'brightness' [R/W] */
  797. entry = create_proc_entry("brightness", S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device));
  798. if (!entry)
  799. ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
  800. "Unable to create 'brightness' fs entry\n"));
  801. else {
  802. entry->proc_fops = &acpi_video_device_brightness_fops;
  803. entry->proc_fops->write = acpi_video_device_write_brightness;
  804. entry->data = acpi_driver_data(device);
  805. entry->owner = THIS_MODULE;
  806. }
  807. /* 'EDID' [R] */
  808. entry = create_proc_entry("EDID", S_IRUGO, acpi_device_dir(device));
  809. if (!entry)
  810. ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
  811. "Unable to create 'brightness' fs entry\n"));
  812. else {
  813. entry->proc_fops = &acpi_video_device_EDID_fops;
  814. entry->data = acpi_driver_data(device);
  815. entry->owner = THIS_MODULE;
  816. }
  817. return_VALUE(0);
  818. }
  819. static int
  820. acpi_video_device_remove_fs (
  821. struct acpi_device *device)
  822. {
  823. struct acpi_video_device *vid_dev;
  824. ACPI_FUNCTION_TRACE("acpi_video_device_remove_fs");
  825. vid_dev = (struct acpi_video_device *) acpi_driver_data(device);
  826. if (!vid_dev || !vid_dev->video || !vid_dev->video->dir)
  827. return_VALUE(-ENODEV);
  828. if (acpi_device_dir(device)) {
  829. remove_proc_entry("info", acpi_device_dir(device));
  830. remove_proc_entry("state", acpi_device_dir(device));
  831. remove_proc_entry("brightness", acpi_device_dir(device));
  832. remove_proc_entry("EDID", acpi_device_dir(device));
  833. remove_proc_entry(acpi_device_bid(device),
  834. vid_dev->video->dir);
  835. acpi_device_dir(device) = NULL;
  836. }
  837. return_VALUE(0);
  838. }
  839. /* video bus */
  840. static int
  841. acpi_video_bus_info_seq_show (
  842. struct seq_file *seq,
  843. void *offset)
  844. {
  845. struct acpi_video_bus *video = (struct acpi_video_bus *) seq->private;
  846. ACPI_FUNCTION_TRACE("acpi_video_bus_info_seq_show");
  847. if (!video)
  848. goto end;
  849. seq_printf(seq, "Switching heads: %s\n",
  850. video->flags.multihead ? "yes":"no");
  851. seq_printf(seq, "Video ROM: %s\n",
  852. video->flags.rom ? "yes":"no");
  853. seq_printf(seq, "Device to be POSTed on boot: %s\n",
  854. video->flags.post ? "yes":"no");
  855. end:
  856. return_VALUE(0);
  857. }
  858. static int
  859. acpi_video_bus_info_open_fs (
  860. struct inode *inode,
  861. struct file *file)
  862. {
  863. return single_open(file, acpi_video_bus_info_seq_show, PDE(inode)->data);
  864. }
  865. static int
  866. acpi_video_bus_ROM_seq_show (
  867. struct seq_file *seq,
  868. void *offset)
  869. {
  870. struct acpi_video_bus *video = (struct acpi_video_bus *) seq->private;
  871. ACPI_FUNCTION_TRACE("acpi_video_bus_ROM_seq_show");
  872. if (!video)
  873. goto end;
  874. printk(KERN_INFO PREFIX "Please implement %s\n", __FUNCTION__);
  875. seq_printf(seq, "<TODO>\n");
  876. end:
  877. return_VALUE(0);
  878. }
  879. static int
  880. acpi_video_bus_ROM_open_fs (
  881. struct inode *inode,
  882. struct file *file)
  883. {
  884. return single_open(file, acpi_video_bus_ROM_seq_show, PDE(inode)->data);
  885. }
  886. static int
  887. acpi_video_bus_POST_info_seq_show (
  888. struct seq_file *seq,
  889. void *offset)
  890. {
  891. struct acpi_video_bus *video = (struct acpi_video_bus *) seq->private;
  892. unsigned long options;
  893. int status;
  894. ACPI_FUNCTION_TRACE("acpi_video_bus_POST_info_seq_show");
  895. if (!video)
  896. goto end;
  897. status = acpi_video_bus_POST_options(video, &options);
  898. if (ACPI_SUCCESS(status)) {
  899. if (!(options & 1)) {
  900. printk(KERN_WARNING PREFIX "The motherboard VGA device is not listed as a possible POST device.\n");
  901. printk(KERN_WARNING PREFIX "This indicate a BIOS bug. Please contact the manufacturer.\n");
  902. }
  903. printk("%lx\n", options);
  904. seq_printf(seq, "can POST: <intgrated video>");
  905. if (options & 2)
  906. seq_printf(seq, " <PCI video>");
  907. if (options & 4)
  908. seq_printf(seq, " <AGP video>");
  909. seq_putc(seq, '\n');
  910. } else
  911. seq_printf(seq, "<not supported>\n");
  912. end:
  913. return_VALUE(0);
  914. }
  915. static int
  916. acpi_video_bus_POST_info_open_fs (
  917. struct inode *inode,
  918. struct file *file)
  919. {
  920. return single_open(file, acpi_video_bus_POST_info_seq_show, PDE(inode)->data);
  921. }
  922. static int
  923. acpi_video_bus_POST_seq_show (
  924. struct seq_file *seq,
  925. void *offset)
  926. {
  927. struct acpi_video_bus *video = (struct acpi_video_bus *) seq->private;
  928. int status;
  929. unsigned long id;
  930. ACPI_FUNCTION_TRACE("acpi_video_bus_POST_seq_show");
  931. if (!video)
  932. goto end;
  933. status = acpi_video_bus_get_POST (video, &id);
  934. if (!ACPI_SUCCESS(status)) {
  935. seq_printf(seq, "<not supported>\n");
  936. goto end;
  937. }
  938. seq_printf(seq, "device posted is <%s>\n", device_decode[id & 3]);
  939. end:
  940. return_VALUE(0);
  941. }
  942. static int
  943. acpi_video_bus_DOS_seq_show (
  944. struct seq_file *seq,
  945. void *offset)
  946. {
  947. struct acpi_video_bus *video = (struct acpi_video_bus *) seq->private;
  948. ACPI_FUNCTION_TRACE("acpi_video_bus_DOS_seq_show");
  949. seq_printf(seq, "DOS setting: <%d>\n", video->dos_setting );
  950. return_VALUE(0);
  951. }
  952. static int
  953. acpi_video_bus_POST_open_fs (
  954. struct inode *inode,
  955. struct file *file)
  956. {
  957. return single_open(file, acpi_video_bus_POST_seq_show, PDE(inode)->data);
  958. }
  959. static int
  960. acpi_video_bus_DOS_open_fs (
  961. struct inode *inode,
  962. struct file *file)
  963. {
  964. return single_open(file, acpi_video_bus_DOS_seq_show, PDE(inode)->data);
  965. }
  966. static ssize_t
  967. acpi_video_bus_write_POST (
  968. struct file *file,
  969. const char __user *buffer,
  970. size_t count,
  971. loff_t *data)
  972. {
  973. int status;
  974. struct seq_file *m = (struct seq_file *) file->private_data;
  975. struct acpi_video_bus *video = (struct acpi_video_bus *) m->private;
  976. char str[12] = {0};
  977. unsigned long opt, options;
  978. ACPI_FUNCTION_TRACE("acpi_video_bus_write_POST");
  979. if (!video || count + 1 > sizeof str)
  980. return_VALUE(-EINVAL);
  981. status = acpi_video_bus_POST_options(video, &options);
  982. if (!ACPI_SUCCESS(status))
  983. return_VALUE(-EINVAL);
  984. if (copy_from_user(str, buffer, count))
  985. return_VALUE(-EFAULT);
  986. str[count] = 0;
  987. opt = strtoul(str, NULL, 0);
  988. if (opt > 3)
  989. return_VALUE(-EFAULT);
  990. /* just in case an OEM 'forget' the motherboard... */
  991. options |= 1;
  992. if (options & (1ul << opt)) {
  993. status = acpi_video_bus_set_POST (video, opt);
  994. if (!ACPI_SUCCESS(status))
  995. return_VALUE(-EFAULT);
  996. }
  997. return_VALUE(count);
  998. }
  999. static ssize_t
  1000. acpi_video_bus_write_DOS (
  1001. struct file *file,
  1002. const char __user *buffer,
  1003. size_t count,
  1004. loff_t *data)
  1005. {
  1006. int status;
  1007. struct seq_file *m = (struct seq_file *) file->private_data;
  1008. struct acpi_video_bus *video = (struct acpi_video_bus *) m->private;
  1009. char str[12] = {0};
  1010. unsigned long opt;
  1011. ACPI_FUNCTION_TRACE("acpi_video_bus_write_DOS");
  1012. if (!video || count + 1 > sizeof str)
  1013. return_VALUE(-EINVAL);
  1014. if (copy_from_user(str, buffer, count))
  1015. return_VALUE(-EFAULT);
  1016. str[count] = 0;
  1017. opt = strtoul(str, NULL, 0);
  1018. if (opt > 7)
  1019. return_VALUE(-EFAULT);
  1020. status = acpi_video_bus_DOS (video, opt & 0x3, (opt & 0x4)>>2);
  1021. if (!ACPI_SUCCESS(status))
  1022. return_VALUE(-EFAULT);
  1023. return_VALUE(count);
  1024. }
  1025. static int
  1026. acpi_video_bus_add_fs (
  1027. struct acpi_device *device)
  1028. {
  1029. struct proc_dir_entry *entry = NULL;
  1030. struct acpi_video_bus *video;
  1031. ACPI_FUNCTION_TRACE("acpi_video_bus_add_fs");
  1032. video = (struct acpi_video_bus *) acpi_driver_data(device);
  1033. if (!acpi_device_dir(device)) {
  1034. acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
  1035. acpi_video_dir);
  1036. if (!acpi_device_dir(device))
  1037. return_VALUE(-ENODEV);
  1038. video->dir = acpi_device_dir(device);
  1039. acpi_device_dir(device)->owner = THIS_MODULE;
  1040. }
  1041. /* 'info' [R] */
  1042. entry = create_proc_entry("info", S_IRUGO, acpi_device_dir(device));
  1043. if (!entry)
  1044. ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to create 'info' fs entry\n"));
  1045. else {
  1046. entry->proc_fops = &acpi_video_bus_info_fops;
  1047. entry->data = acpi_driver_data(device);
  1048. entry->owner = THIS_MODULE;
  1049. }
  1050. /* 'ROM' [R] */
  1051. entry = create_proc_entry("ROM", S_IRUGO, acpi_device_dir(device));
  1052. if (!entry)
  1053. ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to create 'ROM' fs entry\n"));
  1054. else {
  1055. entry->proc_fops = &acpi_video_bus_ROM_fops;
  1056. entry->data = acpi_driver_data(device);
  1057. entry->owner = THIS_MODULE;
  1058. }
  1059. /* 'POST_info' [R] */
  1060. entry = create_proc_entry("POST_info", S_IRUGO, acpi_device_dir(device));
  1061. if (!entry)
  1062. ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to create 'POST_info' fs entry\n"));
  1063. else {
  1064. entry->proc_fops = &acpi_video_bus_POST_info_fops;
  1065. entry->data = acpi_driver_data(device);
  1066. entry->owner = THIS_MODULE;
  1067. }
  1068. /* 'POST' [R/W] */
  1069. entry = create_proc_entry("POST", S_IFREG|S_IRUGO|S_IRUSR, acpi_device_dir(device));
  1070. if (!entry)
  1071. ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to create 'POST' fs entry\n"));
  1072. else {
  1073. entry->proc_fops = &acpi_video_bus_POST_fops;
  1074. entry->proc_fops->write = acpi_video_bus_write_POST;
  1075. entry->data = acpi_driver_data(device);
  1076. entry->owner = THIS_MODULE;
  1077. }
  1078. /* 'DOS' [R/W] */
  1079. entry = create_proc_entry("DOS", S_IFREG|S_IRUGO|S_IRUSR, acpi_device_dir(device));
  1080. if (!entry)
  1081. ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to create 'DOS' fs entry\n"));
  1082. else {
  1083. entry->proc_fops = &acpi_video_bus_DOS_fops;
  1084. entry->proc_fops->write = acpi_video_bus_write_DOS;
  1085. entry->data = acpi_driver_data(device);
  1086. entry->owner = THIS_MODULE;
  1087. }
  1088. return_VALUE(0);
  1089. }
  1090. static int
  1091. acpi_video_bus_remove_fs (
  1092. struct acpi_device *device)
  1093. {
  1094. struct acpi_video_bus *video;
  1095. ACPI_FUNCTION_TRACE("acpi_video_bus_remove_fs");
  1096. video = (struct acpi_video_bus *) acpi_driver_data(device);
  1097. if (acpi_device_dir(device)) {
  1098. remove_proc_entry("info", acpi_device_dir(device));
  1099. remove_proc_entry("ROM", acpi_device_dir(device));
  1100. remove_proc_entry("POST_info", acpi_device_dir(device));
  1101. remove_proc_entry("POST", acpi_device_dir(device));
  1102. remove_proc_entry("DOS", acpi_device_dir(device));
  1103. remove_proc_entry(acpi_device_bid(device),
  1104. acpi_video_dir);
  1105. acpi_device_dir(device) = NULL;
  1106. }
  1107. return_VALUE(0);
  1108. }
  1109. /* --------------------------------------------------------------------------
  1110. Driver Interface
  1111. -------------------------------------------------------------------------- */
  1112. /* device interface */
  1113. static int
  1114. acpi_video_bus_get_one_device (
  1115. struct acpi_device *device,
  1116. struct acpi_video_bus *video)
  1117. {
  1118. unsigned long device_id;
  1119. int status, result;
  1120. struct acpi_video_device *data;
  1121. ACPI_FUNCTION_TRACE("acpi_video_bus_get_one_device");
  1122. if (!device || !video)
  1123. return_VALUE(-EINVAL);
  1124. status = acpi_evaluate_integer(device->handle, "_ADR", NULL, &device_id);
  1125. if (ACPI_SUCCESS(status)) {
  1126. data = kmalloc(sizeof(struct acpi_video_device), GFP_KERNEL);
  1127. if (!data)
  1128. return_VALUE(-ENOMEM);
  1129. memset(data, 0, sizeof(struct acpi_video_device));
  1130. data->handle = device->handle;
  1131. strcpy(acpi_device_name(device), ACPI_VIDEO_DEVICE_NAME);
  1132. strcpy(acpi_device_class(device), ACPI_VIDEO_CLASS);
  1133. acpi_driver_data(device) = data;
  1134. data->device_id = device_id;
  1135. data->video = video;
  1136. data->dev = device;
  1137. switch (device_id & 0xffff) {
  1138. case 0x0100:
  1139. data->flags.crt = 1;
  1140. break;
  1141. case 0x0400:
  1142. data->flags.lcd = 1;
  1143. break;
  1144. case 0x0200:
  1145. data->flags.tvout = 1;
  1146. break;
  1147. default:
  1148. data->flags.unknown = 1;
  1149. break;
  1150. }
  1151. acpi_video_device_bind(video, data);
  1152. acpi_video_device_find_cap(data);
  1153. status = acpi_install_notify_handler(data->handle,
  1154. ACPI_DEVICE_NOTIFY, acpi_video_device_notify, data);
  1155. if (ACPI_FAILURE(status)) {
  1156. ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
  1157. "Error installing notify handler\n"));
  1158. result = -ENODEV;
  1159. goto end;
  1160. }
  1161. down(&video->sem);
  1162. list_add_tail(&data->entry, &video->video_device_list);
  1163. up(&video->sem);
  1164. acpi_video_device_add_fs(device);
  1165. return_VALUE(0);
  1166. }
  1167. end:
  1168. return_VALUE(-ENOENT);
  1169. }
  1170. /*
  1171. * Arg:
  1172. * video : video bus device
  1173. *
  1174. * Return:
  1175. * none
  1176. *
  1177. * Enumerate the video device list of the video bus,
  1178. * bind the ids with the corresponding video devices
  1179. * under the video bus.
  1180. */
  1181. static void
  1182. acpi_video_device_rebind( struct acpi_video_bus *video)
  1183. {
  1184. struct list_head * node, * next;
  1185. list_for_each_safe(node, next, &video->video_device_list) {
  1186. struct acpi_video_device * dev = container_of(node, struct acpi_video_device, entry);
  1187. acpi_video_device_bind( video, dev);
  1188. }
  1189. }
  1190. /*
  1191. * Arg:
  1192. * video : video bus device
  1193. * device : video output device under the video
  1194. * bus
  1195. *
  1196. * Return:
  1197. * none
  1198. *
  1199. * Bind the ids with the corresponding video devices
  1200. * under the video bus.
  1201. */
  1202. static void
  1203. acpi_video_device_bind( struct acpi_video_bus *video,
  1204. struct acpi_video_device *device)
  1205. {
  1206. int i;
  1207. ACPI_FUNCTION_TRACE("acpi_video_device_bind");
  1208. #define IDS_VAL(i) video->attached_array[i].value.int_val
  1209. #define IDS_BIND(i) video->attached_array[i].bind_info
  1210. for (i = 0; IDS_VAL(i) != ACPI_VIDEO_HEAD_INVALID &&
  1211. i < video->attached_count; i++) {
  1212. if (device->device_id == (IDS_VAL(i)& 0xffff)) {
  1213. IDS_BIND(i) = device;
  1214. ACPI_DEBUG_PRINT((ACPI_DB_INFO, "device_bind %d\n", i));
  1215. }
  1216. }
  1217. #undef IDS_VAL
  1218. #undef IDS_BIND
  1219. }
  1220. /*
  1221. * Arg:
  1222. * video : video bus device
  1223. *
  1224. * Return:
  1225. * < 0 : error
  1226. *
  1227. * Call _DOD to enumerate all devices attached to display adapter
  1228. *
  1229. */
  1230. static int acpi_video_device_enumerate(struct acpi_video_bus *video)
  1231. {
  1232. int status;
  1233. int count;
  1234. int i;
  1235. struct acpi_video_enumerated_device *active_device_list;
  1236. struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
  1237. union acpi_object *dod = NULL;
  1238. union acpi_object *obj;
  1239. ACPI_FUNCTION_TRACE("acpi_video_device_enumerate");
  1240. status = acpi_evaluate_object(video->handle, "_DOD", NULL, &buffer);
  1241. if (!ACPI_SUCCESS(status)) {
  1242. ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _DOD\n"));
  1243. return_VALUE(status);
  1244. }
  1245. dod = (union acpi_object *) buffer.pointer;
  1246. if (!dod || (dod->type != ACPI_TYPE_PACKAGE)) {
  1247. ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _DOD data\n"));
  1248. status = -EFAULT;
  1249. goto out;
  1250. }
  1251. ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d video heads in _DOD\n",
  1252. dod->package.count));
  1253. active_device_list= kmalloc(
  1254. (1+dod->package.count)*sizeof(struct acpi_video_enumerated_device),
  1255. GFP_KERNEL);
  1256. if (!active_device_list) {
  1257. status = -ENOMEM;
  1258. goto out;
  1259. }
  1260. count = 0;
  1261. for (i = 0; i < dod->package.count; i++) {
  1262. obj = (union acpi_object *) &dod->package.elements[i];
  1263. if (obj->type != ACPI_TYPE_INTEGER) {
  1264. ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _DOD data\n"));
  1265. active_device_list[i].value.int_val = ACPI_VIDEO_HEAD_INVALID;
  1266. }
  1267. active_device_list[i].value.int_val = obj->integer.value;
  1268. active_device_list[i].bind_info = NULL;
  1269. ACPI_DEBUG_PRINT((ACPI_DB_INFO, "dod element[%d] = %d\n", i, (int) obj->integer.value));
  1270. count++;
  1271. }
  1272. active_device_list[count].value.int_val = ACPI_VIDEO_HEAD_END;
  1273. if(video->attached_array)
  1274. kfree(video->attached_array);
  1275. video->attached_array = active_device_list;
  1276. video->attached_count = count;
  1277. out:
  1278. acpi_os_free(buffer.pointer);
  1279. return_VALUE(status);
  1280. }
  1281. /*
  1282. * Arg:
  1283. * video : video bus device
  1284. * event : Nontify Event
  1285. *
  1286. * Return:
  1287. * < 0 : error
  1288. *
  1289. * 1. Find out the current active output device.
  1290. * 2. Identify the next output device to switch
  1291. * 3. call _DSS to do actual switch.
  1292. */
  1293. static int
  1294. acpi_video_switch_output(
  1295. struct acpi_video_bus *video,
  1296. int event)
  1297. {
  1298. struct list_head * node, * next;
  1299. struct acpi_video_device *dev=NULL;
  1300. struct acpi_video_device *dev_next=NULL;
  1301. struct acpi_video_device *dev_prev=NULL;
  1302. unsigned long state;
  1303. int status = 0;
  1304. ACPI_FUNCTION_TRACE("acpi_video_switch_output");
  1305. list_for_each_safe(node, next, &video->video_device_list) {
  1306. dev = container_of(node, struct acpi_video_device, entry);
  1307. status = acpi_video_device_get_state(dev, &state);
  1308. if (state & 0x2){
  1309. dev_next = container_of(node->next, struct acpi_video_device, entry);
  1310. dev_prev = container_of(node->prev, struct acpi_video_device, entry);
  1311. goto out;
  1312. }
  1313. }
  1314. dev_next = container_of(node->next, struct acpi_video_device, entry);
  1315. dev_prev = container_of(node->prev, struct acpi_video_device, entry);
  1316. out:
  1317. switch (event) {
  1318. case ACPI_VIDEO_NOTIFY_CYCLE:
  1319. case ACPI_VIDEO_NOTIFY_NEXT_OUTPUT:
  1320. acpi_video_device_set_state(dev, 0);
  1321. acpi_video_device_set_state(dev_next, 0x80000001);
  1322. break;
  1323. case ACPI_VIDEO_NOTIFY_PREV_OUTPUT:
  1324. acpi_video_device_set_state(dev, 0);
  1325. acpi_video_device_set_state(dev_prev, 0x80000001);
  1326. default:
  1327. break;
  1328. }
  1329. return_VALUE(status);
  1330. }
  1331. static int
  1332. acpi_video_get_next_level(
  1333. struct acpi_video_device *device,
  1334. u32 level_current,
  1335. u32 event)
  1336. {
  1337. /*Fix me*/
  1338. return level_current;
  1339. }
  1340. static void
  1341. acpi_video_switch_brightness (
  1342. struct acpi_video_device *device,
  1343. int event)
  1344. {
  1345. unsigned long level_current, level_next;
  1346. acpi_video_device_lcd_get_level_current(device, &level_current);
  1347. level_next = acpi_video_get_next_level(device, level_current, event);
  1348. acpi_video_device_lcd_set_level(device, level_next);
  1349. }
  1350. static int
  1351. acpi_video_bus_get_devices (
  1352. struct acpi_video_bus *video,
  1353. struct acpi_device *device)
  1354. {
  1355. int status = 0;
  1356. struct list_head *node, *next;
  1357. ACPI_FUNCTION_TRACE("acpi_video_get_devices");
  1358. acpi_video_device_enumerate(video);
  1359. list_for_each_safe(node, next, &device->children) {
  1360. struct acpi_device *dev = list_entry(node, struct acpi_device, node);
  1361. if (!dev)
  1362. continue;
  1363. status = acpi_video_bus_get_one_device(dev, video);
  1364. if (ACPI_FAILURE(status)) {
  1365. ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Cant attach device\n"));
  1366. continue;
  1367. }
  1368. }
  1369. return_VALUE(status);
  1370. }
  1371. static int
  1372. acpi_video_bus_put_one_device(
  1373. struct acpi_video_device *device)
  1374. {
  1375. struct acpi_video_bus *video;
  1376. ACPI_FUNCTION_TRACE("acpi_video_bus_put_one_device");
  1377. if (!device || !device->video)
  1378. return_VALUE(-ENOENT);
  1379. video = device->video;
  1380. down(&video->sem);
  1381. list_del(&device->entry);
  1382. up(&video->sem);
  1383. acpi_video_device_remove_fs(device->dev);
  1384. return_VALUE(0);
  1385. }
  1386. static int
  1387. acpi_video_bus_put_devices (
  1388. struct acpi_video_bus *video)
  1389. {
  1390. int status;
  1391. struct list_head *node, *next;
  1392. ACPI_FUNCTION_TRACE("acpi_video_bus_put_devices");
  1393. list_for_each_safe(node, next, &video->video_device_list) {
  1394. struct acpi_video_device *data = list_entry(node, struct acpi_video_device, entry);
  1395. if (!data)
  1396. continue;
  1397. status = acpi_video_bus_put_one_device(data);
  1398. if(ACPI_FAILURE(status))
  1399. printk(KERN_WARNING PREFIX "hhuuhhuu bug in acpi video driver.\n");
  1400. if (data->brightness)
  1401. kfree(data->brightness);
  1402. kfree(data);
  1403. }
  1404. return_VALUE(0);
  1405. }
  1406. /* acpi_video interface */
  1407. static int
  1408. acpi_video_bus_start_devices(
  1409. struct acpi_video_bus *video)
  1410. {
  1411. return acpi_video_bus_DOS(video, 1, 0);
  1412. }
  1413. static int
  1414. acpi_video_bus_stop_devices(
  1415. struct acpi_video_bus *video)
  1416. {
  1417. return acpi_video_bus_DOS(video, 0, 1);
  1418. }
  1419. static void
  1420. acpi_video_bus_notify (
  1421. acpi_handle handle,
  1422. u32 event,
  1423. void *data)
  1424. {
  1425. struct acpi_video_bus *video = (struct acpi_video_bus *) data;
  1426. struct acpi_device *device = NULL;
  1427. ACPI_FUNCTION_TRACE("acpi_video_bus_notify");
  1428. printk("video bus notify\n");
  1429. if (!video)
  1430. return_VOID;
  1431. if (acpi_bus_get_device(handle, &device))
  1432. return_VOID;
  1433. switch (event) {
  1434. case ACPI_VIDEO_NOTIFY_SWITCH: /* User request that a switch occur,
  1435. * most likely via hotkey. */
  1436. acpi_bus_generate_event(device, event, 0);
  1437. break;
  1438. case ACPI_VIDEO_NOTIFY_PROBE: /* User plug or remove a video
  1439. * connector. */
  1440. acpi_video_device_enumerate(video);
  1441. acpi_video_device_rebind(video);
  1442. acpi_video_switch_output(video, event);
  1443. acpi_bus_generate_event(device, event, 0);
  1444. break;
  1445. case ACPI_VIDEO_NOTIFY_CYCLE: /* Cycle Display output hotkey pressed.*/
  1446. case ACPI_VIDEO_NOTIFY_NEXT_OUTPUT: /* Next Display output hotkey pressed. */
  1447. case ACPI_VIDEO_NOTIFY_PREV_OUTPUT: /* previous Display output hotkey pressed. */
  1448. acpi_video_switch_output(video, event);
  1449. acpi_bus_generate_event(device, event, 0);
  1450. break;
  1451. default:
  1452. ACPI_DEBUG_PRINT((ACPI_DB_INFO,
  1453. "Unsupported event [0x%x]\n", event));
  1454. break;
  1455. }
  1456. return_VOID;
  1457. }
  1458. static void
  1459. acpi_video_device_notify (
  1460. acpi_handle handle,
  1461. u32 event,
  1462. void *data)
  1463. {
  1464. struct acpi_video_device *video_device = (struct acpi_video_device *) data;
  1465. struct acpi_device *device = NULL;
  1466. ACPI_FUNCTION_TRACE("acpi_video_device_notify");
  1467. printk("video device notify\n");
  1468. if (!video_device)
  1469. return_VOID;
  1470. if (acpi_bus_get_device(handle, &device))
  1471. return_VOID;
  1472. switch (event) {
  1473. case ACPI_VIDEO_NOTIFY_SWITCH: /* change in status (cycle output device) */
  1474. case ACPI_VIDEO_NOTIFY_PROBE: /* change in status (output device status) */
  1475. acpi_bus_generate_event(device, event, 0);
  1476. break;
  1477. case ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS: /* Cycle brightness */
  1478. case ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS: /* Increase brightness */
  1479. case ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS: /* Decrease brightness */
  1480. case ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS: /* zero brightnesss */
  1481. case ACPI_VIDEO_NOTIFY_DISPLAY_OFF: /* display device off */
  1482. acpi_video_switch_brightness (video_device, event);
  1483. acpi_bus_generate_event(device, event, 0);
  1484. break;
  1485. default:
  1486. ACPI_DEBUG_PRINT((ACPI_DB_INFO,
  1487. "Unsupported event [0x%x]\n", event));
  1488. break;
  1489. }
  1490. return_VOID;
  1491. }
  1492. static int
  1493. acpi_video_bus_add (
  1494. struct acpi_device *device)
  1495. {
  1496. int result = 0;
  1497. acpi_status status = 0;
  1498. struct acpi_video_bus *video = NULL;
  1499. ACPI_FUNCTION_TRACE("acpi_video_bus_add");
  1500. if (!device)
  1501. return_VALUE(-EINVAL);
  1502. video = kmalloc(sizeof(struct acpi_video_bus), GFP_KERNEL);
  1503. if (!video)
  1504. return_VALUE(-ENOMEM);
  1505. memset(video, 0, sizeof(struct acpi_video_bus));
  1506. video->handle = device->handle;
  1507. strcpy(acpi_device_name(device), ACPI_VIDEO_BUS_NAME);
  1508. strcpy(acpi_device_class(device), ACPI_VIDEO_CLASS);
  1509. acpi_driver_data(device) = video;
  1510. acpi_video_bus_find_cap(video);
  1511. result = acpi_video_bus_check(video);
  1512. if (result)
  1513. goto end;
  1514. result = acpi_video_bus_add_fs(device);
  1515. if (result)
  1516. goto end;
  1517. init_MUTEX(&video->sem);
  1518. INIT_LIST_HEAD(&video->video_device_list);
  1519. acpi_video_bus_get_devices(video, device);
  1520. acpi_video_bus_start_devices(video);
  1521. status = acpi_install_notify_handler(video->handle,
  1522. ACPI_DEVICE_NOTIFY, acpi_video_bus_notify, video);
  1523. if (ACPI_FAILURE(status)) {
  1524. ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
  1525. "Error installing notify handler\n"));
  1526. result = -ENODEV;
  1527. goto end;
  1528. }
  1529. printk(KERN_INFO PREFIX "%s [%s] (multi-head: %s rom: %s post: %s)\n",
  1530. ACPI_VIDEO_DEVICE_NAME, acpi_device_bid(device),
  1531. video->flags.multihead ? "yes":"no",
  1532. video->flags.rom ? "yes":"no",
  1533. video->flags.post ? "yes":"no");
  1534. end:
  1535. if (result) {
  1536. acpi_video_bus_remove_fs(device);
  1537. kfree(video);
  1538. }
  1539. return_VALUE(result);
  1540. }
  1541. static int
  1542. acpi_video_bus_remove (
  1543. struct acpi_device *device,
  1544. int type)
  1545. {
  1546. acpi_status status = 0;
  1547. struct acpi_video_bus *video = NULL;
  1548. ACPI_FUNCTION_TRACE("acpi_video_bus_remove");
  1549. if (!device || !acpi_driver_data(device))
  1550. return_VALUE(-EINVAL);
  1551. video = (struct acpi_video_bus *) acpi_driver_data(device);
  1552. acpi_video_bus_stop_devices(video);
  1553. status = acpi_remove_notify_handler(video->handle,
  1554. ACPI_DEVICE_NOTIFY, acpi_video_bus_notify);
  1555. if (ACPI_FAILURE(status))
  1556. ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
  1557. "Error removing notify handler\n"));
  1558. acpi_video_bus_put_devices(video);
  1559. acpi_video_bus_remove_fs(device);
  1560. if (video->attached_array)
  1561. kfree(video->attached_array);
  1562. kfree(video);
  1563. return_VALUE(0);
  1564. }
  1565. static int
  1566. acpi_video_bus_match (
  1567. struct acpi_device *device,
  1568. struct acpi_driver *driver)
  1569. {
  1570. acpi_handle h_dummy1;
  1571. acpi_handle h_dummy2;
  1572. acpi_handle h_dummy3;
  1573. ACPI_FUNCTION_TRACE("acpi_video_bus_match");
  1574. if (!device || !driver)
  1575. return_VALUE(-EINVAL);
  1576. /* Since there is no HID, CID for ACPI Video drivers, we have
  1577. * to check well known required nodes for each feature we support.
  1578. */
  1579. /* Does this device able to support video switching ? */
  1580. if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOD", &h_dummy1)) &&
  1581. ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOS", &h_dummy2)))
  1582. return_VALUE(0);
  1583. /* Does this device able to retrieve a video ROM ? */
  1584. if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_ROM", &h_dummy1)))
  1585. return_VALUE(0);
  1586. /* Does this device able to configure which video head to be POSTed ? */
  1587. if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_VPO", &h_dummy1)) &&
  1588. ACPI_SUCCESS(acpi_get_handle(device->handle, "_GPD", &h_dummy2)) &&
  1589. ACPI_SUCCESS(acpi_get_handle(device->handle, "_SPD", &h_dummy3)))
  1590. return_VALUE(0);
  1591. return_VALUE(-ENODEV);
  1592. }
  1593. static int __init
  1594. acpi_video_init (void)
  1595. {
  1596. int result = 0;
  1597. ACPI_FUNCTION_TRACE("acpi_video_init");
  1598. /*
  1599. acpi_dbg_level = 0xFFFFFFFF;
  1600. acpi_dbg_layer = 0x08000000;
  1601. */
  1602. acpi_video_dir = proc_mkdir(ACPI_VIDEO_CLASS, acpi_root_dir);
  1603. if (!acpi_video_dir)
  1604. return_VALUE(-ENODEV);
  1605. acpi_video_dir->owner = THIS_MODULE;
  1606. result = acpi_bus_register_driver(&acpi_video_bus);
  1607. if (result < 0) {
  1608. remove_proc_entry(ACPI_VIDEO_CLASS, acpi_root_dir);
  1609. return_VALUE(-ENODEV);
  1610. }
  1611. return_VALUE(0);
  1612. }
  1613. static void __exit
  1614. acpi_video_exit (void)
  1615. {
  1616. ACPI_FUNCTION_TRACE("acpi_video_exit");
  1617. acpi_bus_unregister_driver(&acpi_video_bus);
  1618. remove_proc_entry(ACPI_VIDEO_CLASS, acpi_root_dir);
  1619. return_VOID;
  1620. }
  1621. module_init(acpi_video_init);
  1622. module_exit(acpi_video_exit);