sync hh.org
[hh.org.git] / arch / arm / mach-sa1100 / h3600_hal.c
blobfa6231cc2b227999d783e6333d942addfe48cf34
1 /*
2 * Hardware abstraction layer for HP iPAQ H3xxx Pocket Computers
4 * Copyright 2000,2001 Compaq Computer Corporation.
6 * Use consistent with the GNU GPL is permitted,
7 * provided that this copyright notice is
8 * preserved in its entirety in all copies and derived works.
10 * COMPAQ COMPUTER CORPORATION MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
11 * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
12 * FITNESS FOR ANY PARTICULAR PURPOSE.
14 * Andrew Christian
15 * October, 2001
18 #include <linux/module.h>
19 #include <linux/version.h>
21 #include <linux/init.h>
22 #include <linux/fs.h>
23 #include <linux/delay.h>
24 #include <linux/poll.h>
25 #include <asm/uaccess.h> /* get_user,copy_to_user */
26 #include <linux/string.h>
27 #include <linux/interrupt.h>
28 #include <linux/sysctl.h>
29 #include <linux/console.h>
30 #include <linux/devfs_fs_kernel.h>
32 #include <linux/tqueue.h>
33 #include <linux/sched.h>
34 #include <linux/pm.h>
35 #include <linux/proc_fs.h>
36 #include <linux/apm_bios.h>
37 #include <linux/kmod.h>
39 #include <asm/hardware.h>
40 #include <asm/arch-sa1100/h3600_hal.h>
42 #define H3600_HAL_PROC_DIR "hal"
44 /* Interface supplied by the low-level microcontroller driver */
45 struct h3600_hal_ops *h3600_hal_ops = NULL;
46 EXPORT_SYMBOL(h3600_hal_ops);
48 static struct h3600_driver_ops g_driver_ops;
50 /* Global values */
51 static unsigned char flite_brightness = 25;
52 static int max_flite_brightness = 255;
53 static enum flite_pwr flite_power = FLITE_PWR_ON;
54 static int lcd_active = 1;
55 static unsigned char screen_contrast = 100;
57 /* Parameters */
59 MODULE_PARM(flite_brightness,"b");
60 MODULE_PARM_DESC(flite_brightness,"Initial brightness setting of the frontlight");
61 MODULE_PARM(max_flite_brightness,"i");
62 MODULE_PARM_DESC(max_flite_brightness,"Maximum allowable brightness setting of the frontlight");
63 MODULE_PARM(flite_power,"i");
64 MODULE_PARM_DESC(flite_power,"Initial power setting of the frontlight (on/off)");
65 MODULE_PARM(screen_contrast,"i");
66 MODULE_PARM_DESC(screen_contrast,"Initial screen contrast (for H3100 only)");
68 MODULE_AUTHOR("Andrew Christian");
69 MODULE_DESCRIPTION("Hardware abstraction layer for the iPAQ H3600");
70 MODULE_LICENSE("Dual BSD/GPL");
72 /***********************************************************************************/
73 /* General callbacks */
74 /***********************************************************************************/
76 int h3600_set_flite(enum flite_pwr pwr, unsigned char brightness)
78 if (0) printk("### %s: pwr=%d brightness=%d lcdactive=%d\n",
79 __FUNCTION__, pwr, brightness, lcd_active );
81 if ( brightness > max_flite_brightness )
82 brightness = max_flite_brightness;
84 /* Save the current settings */
85 flite_power = pwr;
86 flite_brightness = brightness;
88 return h3600_backlight_control( (lcd_active ? flite_power : FLITE_PWR_OFF),
89 (pwr == FLITE_PWR_ON && lcd_active ? flite_brightness : 0) );
92 void h3600_get_flite( struct h3600_ts_backlight *bl )
94 bl->power = flite_power;
95 bl->brightness = flite_brightness;
98 int h3600_set_contrast( unsigned char contrast )
100 if (0) printk("%s: contrast=%d\n", __FUNCTION__, contrast );
102 screen_contrast = contrast;
103 return h3600_contrast_control( screen_contrast );
106 void h3600_get_contrast( u_char *contrast )
108 *contrast = screen_contrast;
111 int h3600_toggle_frontlight( void )
113 return h3600_set_flite( 1 - flite_power, flite_brightness );
116 EXPORT_SYMBOL(h3600_get_flite);
117 EXPORT_SYMBOL(h3600_set_flite);
118 EXPORT_SYMBOL(h3600_get_contrast);
119 EXPORT_SYMBOL(h3600_set_contrast);
120 EXPORT_SYMBOL(h3600_toggle_frontlight);
122 /* TODO
124 Check on blanking modes. Right now we seem to have problems with the console
125 blanking. Its recovery appears to be in interrupt context. Question - is this
126 function always called in interrupt context? If it is, move the h3600_flite_control
127 to a task. If not, should we be using the power manager?
129 This function is called by sa1100fb to turn on and off the backlight. There
130 are several reasons it can be called:
132 1. The framebuffer is being shut down from a suspend/resume.
133 2. Someone like an X server has requested blanking
135 On a blank request, we shut off the backlight. On an "unblank" request,
136 we restore the backlight to its prior setting.
139 static void h3600_hal_backlight_helper(int blank)
141 if (0) printk(" %s: backlight=%d interrupt=%d\n", __FUNCTION__, blank, in_interrupt());
143 lcd_active = !blank;
144 h3600_set_flite( flite_power, flite_brightness );
147 void h3600_hal_keypress( unsigned char key )
149 if ( g_driver_ops.keypress )
150 g_driver_ops.keypress(key);
153 void h3600_hal_touchpanel( unsigned short x, unsigned short y, int down )
155 if ( g_driver_ops.touchpanel )
156 g_driver_ops.touchpanel(x,y,down);
159 void h3600_hal_option_detect( int present )
161 if ( g_driver_ops.option_detect )
162 g_driver_ops.option_detect(present);
165 EXPORT_SYMBOL(h3600_hal_keypress);
166 EXPORT_SYMBOL(h3600_hal_touchpanel);
167 EXPORT_SYMBOL(h3600_hal_option_detect);
169 /***********************************************************************************/
170 /* Functions exported for use by the kernel and kernel modules */
171 /***********************************************************************************/
173 int h3600_apm_get_power_status(u_char *ac_line_status,
174 u_char *battery_status,
175 u_char *battery_flag,
176 u_char *battery_percentage,
177 u_short *battery_life)
179 struct h3600_battery bstat;
180 unsigned char ac = APM_AC_UNKNOWN;
181 unsigned char level = APM_BATTERY_STATUS_UNKNOWN;
182 int status, result;
184 result = h3600_get_battery(&bstat);
185 if (result) {
186 printk("%s: unable to access battery information: result=%d\n", __FUNCTION__, result);
187 return 0;
190 switch (bstat.ac_status) {
191 case H3600_AC_STATUS_AC_OFFLINE:
192 ac = APM_AC_OFFLINE;
193 break;
194 case H3600_AC_STATUS_AC_ONLINE:
195 ac = APM_AC_ONLINE;
196 break;
197 case H3600_AC_STATUS_AC_BACKUP:
198 ac = APM_AC_BACKUP;
199 break;
202 if (ac_line_status != NULL)
203 *ac_line_status = ac;
205 status = bstat.battery[0].status;
206 if (status & (H3600_BATT_STATUS_CHARGING | H3600_BATT_STATUS_CHARGE_MAIN))
207 level = APM_BATTERY_STATUS_CHARGING;
208 else if (status & (H3600_BATT_STATUS_HIGH | H3600_BATT_STATUS_FULL))
209 level = APM_BATTERY_STATUS_HIGH;
210 else if (status & H3600_BATT_STATUS_LOW)
211 level = APM_BATTERY_STATUS_LOW;
212 else if (status & H3600_BATT_STATUS_CRITICAL)
213 level = APM_BATTERY_STATUS_CRITICAL;
215 if (battery_status != NULL)
216 *battery_status = level;
218 if (battery_percentage != NULL)
219 *battery_percentage = bstat.battery[0].percentage;
221 /* assuming C/5 discharge rate */
222 if (battery_life != NULL) {
223 *battery_life = bstat.battery[0].life;
224 *battery_life |= 0x8000; /* Flag for minutes */
227 return 1;
230 EXPORT_SYMBOL(h3600_apm_get_power_status);
232 /***********************************************************************************/
233 /* Proc filesystem interface */
234 /***********************************************************************************/
236 static struct ctl_table h3600_hal_table[] =
238 {3, "max_flite_brightness", &max_flite_brightness, sizeof(max_flite_brightness),
239 0666, NULL, &proc_dointvec},
243 static struct ctl_table h3600_hal_dir_table[] =
245 {11, "hal", NULL, 0, 0555, h3600_hal_table},
249 static struct ctl_table_header *h3600_hal_sysctl_header = NULL;
250 static struct proc_dir_entry *hal_proc_dir = NULL;
252 enum hal_proc_index {
253 HAL_DONE,
254 HAL_VERSION,
255 HAL_THERMAL_SENSOR,
256 HAL_BATTERY,
257 HAL_LIGHT_SENSOR,
258 HAL_ASSETS,
259 HAL_MODEL,
260 HAL_SCREEN_ROTATION
263 struct h3600_proc_item {
264 const char *name;
265 enum hal_proc_index id;
268 static struct h3600_proc_item g_procitems[] = {
269 {"version", HAL_VERSION },
270 {"thermal", HAL_THERMAL_SENSOR },
271 {"battery", HAL_BATTERY },
272 {"light_sensor", HAL_LIGHT_SENSOR },
273 {"assets", HAL_ASSETS },
274 {"model", HAL_MODEL },
275 {"screen_rotation", HAL_SCREEN_ROTATION },
276 {"done", HAL_DONE },
279 struct battery_flag_name {
280 int bits;
281 char *name;
284 static struct battery_flag_name battery_chemistry[] = {
285 { H3600_BATT_CHEM_ALKALINE, "alkaline" },
286 { H3600_BATT_CHEM_NICD, "NiCd" },
287 { H3600_BATT_CHEM_NIMH, "NiMH" },
288 { H3600_BATT_CHEM_LION, "Li-ion" },
289 { H3600_BATT_CHEM_LIPOLY, "Li-Polymer" },
290 { H3600_BATT_CHEM_NOT_INSTALLED, "Not installed" },
291 { H3600_BATT_CHEM_UNKNOWN, "unknown" },
292 { -1, "?" }
295 static struct battery_flag_name ac_status[] = {
296 { H3600_AC_STATUS_AC_OFFLINE, "offline" },
297 { H3600_AC_STATUS_AC_ONLINE, "online" },
298 { H3600_AC_STATUS_AC_BACKUP, "backup" },
299 { H3600_AC_STATUS_AC_UNKNOWN, "unknown" },
300 { -1, "?" }
303 static struct battery_flag_name battery_status[] = {
304 { H3600_BATT_STATUS_HIGH, "high" },
305 { H3600_BATT_STATUS_LOW, "low" },
306 { H3600_BATT_STATUS_CRITICAL, "critical" },
307 { H3600_BATT_STATUS_CHARGING, "charging" },
308 { H3600_BATT_STATUS_CHARGE_MAIN, "charge main" },
309 { H3600_BATT_STATUS_DEAD, "dead" },
310 { H3600_BATT_STATUS_FULL, "fully charged" },
311 { H3600_BATT_STATUS_NOBATT, "no battery" },
312 { -1, "?" }
315 static char * extract_flag_name( struct battery_flag_name *list, unsigned char value )
317 while ( list->bits != -1 && list->bits != value )
318 list++;
319 return list->name;
322 static void battery_status_to_string (unsigned char value, char *buf)
324 char *p = buf;
325 struct battery_flag_name *f = &battery_status[0];
327 if (value == H3600_BATT_STATUS_UNKNOWN) {
328 strcpy (buf, "unknown");
329 return;
332 while (f->bits != -1) {
333 if (value & (f->bits)) {
334 if (p != buf) {
335 *p++ = ';';
336 *p++ = ' ';
338 strcpy (p, f->name);
339 p += strlen (f->name);
341 f++;
344 *p = 0;
347 struct params_list {
348 int value;
349 char *name;
352 static struct params_list product_id[] = {
353 { 2, "Palm" },
354 { -1, "" },
357 static struct params_list page_mode[] = {
358 { 0, "Flash" },
359 { 1, "ROM" },
360 { -1, "" },
363 /* These are guesses */
364 static struct params_list country_id[] = {
365 { 0, "USA" },
366 { 1, "English" },
367 { 2, "German" },
368 { 3, "French" },
369 { 4, "Italian" },
370 { 5, "Spanish" },
371 { 0x8001, "Traditional Chinese" },
372 { 0x8002, "Simplified Chinese" },
373 { 0x8003, "Japanese" },
374 { -1, "" },
377 #define BASIC_FORMAT "%20s : "
379 static char * lookup_params( struct params_list *list, int value )
381 if ( !list )
382 return NULL;
384 while ( list->value != -1 && list->value != value )
385 list++;
386 return list->name;
389 static char * asset_print_tchar( char *p, struct h3600_asset *asset,
390 unsigned char *name, struct params_list *list )
392 int len = ASSET_TCHAR_LEN(asset->type);
393 unsigned char *data = asset->a.tchar;
395 // printk(" * Printing %s at %p, length = %d (%p)\n", name, data, len, p );
397 p += sprintf(p, BASIC_FORMAT, name );
398 for ( ; len > 0 ; len-- ) {
399 if ( *data )
400 *p++ = *data;
401 data++;
403 *p++ = '\n';
404 return p;
407 static char * asset_print_word( char *p, struct h3600_asset *asset,
408 unsigned char *name, struct params_list *list )
410 unsigned short value = asset->a.vshort;
411 char *param = lookup_params(list,value);
413 // printk(" * Printing %s value %d (%p)\n", name, value, p );
415 if ( param )
416 p += sprintf(p, BASIC_FORMAT "%d (%s)\n", name, value, param );
417 else
418 p += sprintf(p, BASIC_FORMAT "%d\n", name, value);
419 return p;
423 static struct params_table params_table[] = {
424 { 0, PARAMS_TCHAR, 5, "HM Version" },
425 { 10, PARAMS_TCHAR, 20, "Serial #" },
426 { 50, PARAMS_TCHAR, 10, "Module ID" },
427 { 70, PARAMS_TCHAR, 5, "Product Revision" },
428 { 80, PARAMS_WORD, 0, "Product ID", product_id },
429 { 82, PARAMS_WORD, 0, "Frame Rate" },
430 { 84, PARAMS_WORD, 0, "Page Mode", page_mode },
431 { 86, PARAMS_WORD, 0, "Country ID", country_id },
432 { 88, PARAMS_WORD, 0, "Is Color Display" },
433 { 90, PARAMS_WORD, 0, "ROM Size" },
434 { 92, PARAMS_WORD, 0, "RAM Size" },
435 { 94, PARAMS_WORD, 0, "Horizontal pixels" },
436 { 96, PARAMS_WORD, 0, "Vertical pixels" },
437 { 0, PARAMS_DONE, 0, NULL }
441 //#define PRINT_TCHAR(_p,_name,_x) _p = print_param_tchar(_p, _name, _x, sizeof(_x))
443 typedef char * (*asset_printer)( char *p, struct h3600_asset *asset,
444 unsigned char * name, struct params_list *list );
446 static asset_printer asset_printers[] = {
447 asset_print_tchar,
448 asset_print_word,
451 struct params_table {
452 unsigned long asset;
453 char *name;
454 struct params_list *list;
457 static struct params_table params_table[] = {
458 { ASSET_HM_VERSION, "HM Version" },
459 { ASSET_SERIAL_NUMBER, "Serial #" },
460 { ASSET_MODULE_ID, "Module ID" },
461 { ASSET_PRODUCT_REVISION, "Product Revision" },
462 { ASSET_PRODUCT_ID, "Product ID", product_id },
463 { ASSET_FRAME_RATE, "Frame Rate" },
464 { ASSET_PAGE_MODE, "Page Mode", page_mode },
465 { ASSET_COUNTRY_ID, "Country ID", country_id },
466 { ASSET_IS_COLOR_DISPLAY, "Is Color Display" },
467 { ASSET_ROM_SIZE, "ROM Size" },
468 { ASSET_RAM_SIZE, "RAM Size" },
469 { ASSET_HORIZONTAL_PIXELS,"Horizontal pixels" },
470 { ASSET_VERTICAL_PIXELS, "Vertical pixels" }
473 static char * h3600_hal_parse_eeprom( char *p )
475 struct h3600_asset asset;
476 int i;
477 int retval;
479 // printk( __FUNCTION__ " : called with %p\n", p );
481 /* Suck in the data */
482 // retval = h3600_asset_read( &asset );
483 // if ( retval ) {
484 // p += sprintf(p,"Error value %d\n", retval);
485 // return p;
486 // }
488 // retval = sizeof(asset.hm_version);
489 // p = print_param_tchar( p, "HM Version", asset.hm_version, retval );
490 // printk(" *** assets at %p\n", &asset );
492 for ( i = 0 ; i < (sizeof(params_table) / sizeof(struct params_table)) ; i++ ) {
493 // printk( " ** parsing %d 0x%08lX %ld\n", i, params_table[i].asset,
494 // ASSET_TYPE(params_table[i].asset));
495 asset.type = params_table[i].asset;
496 retval = h3600_asset_read( &asset );
497 if ( retval ) {
498 p += sprintf(p,"Error value %d\n", retval);
499 return p;
501 p = asset_printers[ASSET_TYPE(params_table[i].asset)]( p, &asset,
502 params_table[i].name,
503 params_table[i].list );
505 /* PRINT_TCHAR( p, "HM Version", asset.hm_version );
506 PRINT_TCHAR( p, "Serial #", asset.serial_number );
507 PRINT_TCHAR( p, "Module ID", asset.module_id );
508 PRINT_TCHAR( p, "Product Revision", asset.product_revision );
510 p = print_param_word( p, "Product ID", asset.product_id, product_id );
511 p = print_param_word( p, "Frame Rate", asset.frame_rate, NULL );
512 p = print_param_word( p, "Page Mode", asset.page_mode, page_mode );
513 p = print_param_word( p, "Country ID", asset.country_id, country_id );
514 p = print_param_word( p, "Is Color Display", asset.is_color_display, NULL );
515 p = print_param_word( p, "ROM Size", asset.rom_size, NULL );
516 p = print_param_word( p, "RAM Size", asset.ram_size, NULL );
517 p = print_param_word( p, "Horizontal pixels", asset.horizontal_pixels, NULL );
518 p = print_param_word( p, "Vertical pixels", asset.vertical_pixels, NULL );*/
520 // printk( __FUNCTION__ " : returning %p\n", p );
521 return p;
525 #include <linux/ctype.h>
526 #define DUMP_BUF_SIZE 16
527 #define MYPRINTABLE(x) \
528 ( ((x)<='z' && (x)>='a') || ((x)<='Z' && (x)>='A') || isdigit(x) || (x)==':' )
530 static void dump_mem( unsigned char *p, int count )
532 u_char pbuf[DUMP_BUF_SIZE + 1];
533 int len;
534 int i;
536 printk(__FUNCTION__ " %p %d\n", p, count);
538 while ( count ) {
539 len = count;
540 if ( len > DUMP_BUF_SIZE )
541 len = DUMP_BUF_SIZE;
543 for ( i = 0 ; i < len ; i++ ) {
544 printk(" %02x", *p );
545 pbuf[i] = ( MYPRINTABLE(*p) ? *p : '.' );
546 count--;
547 p++;
550 pbuf[i] = '\0';
551 printk(" %s\n", pbuf);
556 static int h3600_hal_proc_item_read(char *page, char **start, off_t off,
557 int count, int *eof, void *data)
559 char *p = page;
560 int len;
561 int retval = 0;
563 if (0) printk("%s: %p %p %ld %d %p %p\n", __FUNCTION__, page, start, off, count, eof, data );
565 switch ((int)data) {
566 case HAL_VERSION:
568 struct h3600_ts_version v;
569 retval = h3600_get_version( &v );
570 if ( !retval ) {
571 p += sprintf(p, "Host : %s\n", v.host_version );
572 p += sprintf(p, "Pack : %s\n", v.pack_version );
573 p += sprintf(p, "Boot type : 0x%02x\n", v.boot_type );
575 break;
577 case HAL_THERMAL_SENSOR:
579 unsigned short v;
580 retval = h3600_get_thermal_sensor( &v );
581 if ( !retval )
582 p += sprintf(p, "0x%04x\n", v );
583 break;
585 case HAL_BATTERY:
587 struct h3600_battery v;
588 retval = h3600_get_battery( &v );
589 if ( !retval ) {
590 char buf[256];
591 int i;
592 p += sprintf(p, "AC status : %x (%s)\n", v.ac_status,
593 extract_flag_name(ac_status,v.ac_status));
595 for ( i = 0 ; i < v.battery_count ; i++ ) {
596 p += sprintf(p, "Battery #%d\n", i);
597 p += sprintf(p, " Chemistry : 0x%02x (%s)\n",
598 v.battery[i].chemistry,
599 extract_flag_name(battery_chemistry,
600 v.battery[i].chemistry));
601 battery_status_to_string (v.battery[i].status, buf);
602 p += sprintf(p, " Status : 0x%02x (%s)\n",
603 v.battery[i].status,
604 buf);
605 if ( i == 0 )
606 p += sprintf(p, " Voltage : 0x%04x (%4d mV)\n",
607 v.battery[i].voltage,
608 v.battery[i].voltage * 5000 / 1024);
609 p += sprintf(p, " Percentage : 0x%02x", v.battery[i].percentage);
610 if ( v.battery[i].percentage == 0xff )
611 p += sprintf(p, " (unknown)\n");
612 else
613 p += sprintf(p, " (%d%%)\n", v.battery[i].percentage);
614 if ( i == 0 )
615 p += sprintf(p, " Life (min) : %d\n", v.battery[i].life);
618 break;
620 case HAL_LIGHT_SENSOR:
622 unsigned char level;
623 retval = h3600_get_light_sensor(&level);
624 if (!retval)
625 p += sprintf(p,"0x%02x\n", level );
626 break;
628 case HAL_ASSETS:
629 p = h3600_hal_parse_eeprom( p );
630 break;
631 case HAL_MODEL:
632 p += sprintf(p,"%s\n", h3600_generic_name() );
633 break;
634 case HAL_SCREEN_ROTATION:
635 p += sprintf(p,"%s\n", h3600_screen_rotation() );
636 break;
637 default:
638 p += sprintf(p,"Unsupported item %d\n", (int)data);
639 break;
642 if ( retval ) {
643 p += sprintf(p,"Error value %d\n", retval);
646 // dump_mem( page, p - page );
647 len = (p - page) - off;
648 if (len < 0)
649 len = 0;
651 *eof = (len <= count) ? 1 : 0;
652 *start = page + off;
654 return len;
658 /***********************************************************************************/
659 /* Registration functions from low level and from device drivers */
660 /***********************************************************************************/
662 int h3600_hal_register_interface( struct h3600_hal_ops *ops )
664 if ( !ops || !ops->owner )
665 return -EFAULT;
667 h3600_hal_ops = ops;
668 /* Initialize our screen and frontlight */
669 h3600_set_flite( flite_power, flite_brightness );
670 h3600_set_contrast( screen_contrast );
672 return 0;
675 void h3600_hal_unregister_interface( struct h3600_hal_ops *ops )
677 h3600_hal_ops = NULL;
680 EXPORT_SYMBOL(h3600_hal_register_interface);
681 EXPORT_SYMBOL(h3600_hal_unregister_interface);
683 #define HAL_REG(x) \
684 if ( ops->x ) g_driver_ops.x = ops->x
686 #define HAL_UNREG(x) \
687 if ( ops->x ) g_driver_ops.x = NULL
689 int h3600_hal_register_driver( struct h3600_driver_ops *ops )
691 HAL_REG(keypress);
692 HAL_REG(touchpanel);
693 HAL_REG(option_detect);
694 return 0;
697 void h3600_hal_unregister_driver( struct h3600_driver_ops *ops )
699 HAL_UNREG(keypress);
700 HAL_UNREG(touchpanel);
701 HAL_UNREG(option_detect);
704 EXPORT_SYMBOL(h3600_hal_register_driver);
705 EXPORT_SYMBOL(h3600_hal_unregister_driver);
708 /***********************************************************************************/
709 /* Initialization */
710 /***********************************************************************************/
712 #ifdef CONFIG_FB_SA1100
713 extern void (*sa1100fb_blank_helper)(int blank);
714 #endif
715 #ifdef CONFIG_FB_PXA
716 extern void (*pxafb_blank_helper)(int blank);
717 #endif
719 int __init h3600_hal_init_module(void)
721 int i;
722 printk(KERN_INFO "H3600 Registering HAL abstraction layer\n");
724 /* Request the appropriate underlying module to provide services */
725 /* TODO: We've put this here to avoid having to add another /etc/module
726 line for people upgrading their kernel. In the future, we'd like to
727 automatically request and load the appropriate subsystem based on the
728 type of iPAQ owned */
729 if ( machine_is_h3100() || machine_is_h3600() ) {
730 request_module("h3600_micro");
732 else if ( machine_is_h3800() ) {
733 request_module("h3600_asic");
735 else if ( machine_is_h3900() ) {
736 request_module("h3900_asic");
737 } else if ( machine_is_h5400() ) {
738 request_module("h5400_asic");
739 } else if ( machine_is_h1900() ) {
740 request_module("h1900_asic");
743 h3600_hal_sysctl_header = register_sysctl_table(h3600_hal_dir_table, 0);
744 #ifdef CONFIG_FB_SA1100
745 sa1100fb_blank_helper = h3600_hal_backlight_helper;
746 #endif
747 #ifdef CONFIG_FB_PXA
748 pxafb_blank_helper = h3600_hal_backlight_helper;
749 #endif
751 /* Register in /proc filesystem */
752 hal_proc_dir = proc_mkdir(H3600_HAL_PROC_DIR, NULL);
753 if ( hal_proc_dir )
754 for ( i = 0 ; g_procitems[i].id != HAL_DONE ; i++ )
755 create_proc_read_entry(g_procitems[i].name, 0, hal_proc_dir,
756 h3600_hal_proc_item_read, (void *) g_procitems[i].id );
757 else
758 printk(KERN_ALERT "%s: unable to create proc entry %s\n", __FUNCTION__, H3600_HAL_PROC_DIR);
759 return 0;
762 void h3600_hal_cleanup_module(void)
764 int i;
765 printk(KERN_INFO "H3600 shutting down HAL abstraction layer\n");
767 #ifdef CONFIG_FB_SA1100
768 sa1100fb_blank_helper = NULL;
769 #endif
770 #ifdef CONFIG_FB_PXA
771 pxafb_blank_helper = NULL;
772 #endif
773 unregister_sysctl_table(h3600_hal_sysctl_header);
775 if ( hal_proc_dir ) {
776 for ( i = 0 ; g_procitems[i].id != HAL_DONE ; i++ )
777 remove_proc_entry(g_procitems[i].name, hal_proc_dir);
778 remove_proc_entry(H3600_HAL_PROC_DIR, NULL );
779 hal_proc_dir = NULL;
783 module_init(h3600_hal_init_module);
784 module_exit(h3600_hal_cleanup_module);