static int __init s3c2410ts_probe(struct platform_device *pdev) { int rc; struct s3c2410_ts_mach_info *info; struct input_dev *input_dev; int ret = 0;
dev_info(&pdev->dev, "Starting\n");
info = (struct s3c2410_ts_mach_info *)pdev->dev.platform_data;//获得平台设备数据
if (!info) { dev_err(&pdev->dev, "Hm... too bad: no platform data for ts\n"); return -EINVAL; }
#ifdef CONFIG_TOUCHSCREEN_S3C2410_DEBUG printk(DEBUG_LVL "Entering s3c2410ts_init\n"); #endif
adc_clock = clk_get(NULL, "adc"); if (!adc_clock) { dev_err(&pdev->dev, "failed to get adc clock source\n"); return -ENOENT; } clk_enable(adc_clock);
#ifdef CONFIG_TOUCHSCREEN_S3C2410_DEBUG printk(DEBUG_LVL "got and enabled clock\n"); #endif
base_addr = ioremap(S3C2410_PA_ADC,0x20);//将PA_ADC寄存器重映射到内存上
if (base_addr == NULL) { dev_err(&pdev->dev, "Failed to remap register block\n"); ret = -ENOMEM; goto bail0; }
/* If we acutally are a S3C2410: Configure GPIOs */ if (!strcmp(pdev->name, "s3c2410-ts")) s3c2410_ts_connect();//初始化相关gpio口
if ((info->presc & 0xff) > 0) writel(S3C2410_ADCCON_PRSCEN | S3C2410_ADCCON_PRSCVL(info->presc&0xFF), base_addr + S3C2410_ADCCON); else writel(0, base_addr+S3C2410_ADCCON);
/* Initialise registers */ if ((info->delay & 0xffff) > 0) writel(info->delay & 0xffff, base_addr + S3C2410_ADCDLY);
writel(WAIT4INT(0), base_addr + S3C2410_ADCTSC);
/* Initialise input stuff */ memset(&ts, 0, sizeof(struct s3c2410ts)); input_dev = input_allocate_device();
if (!input_dev) { dev_err(&pdev->dev, "Unable to allocate the input device\n"); ret = -ENOMEM; goto bail1; }
//初始化input设备
ts.dev = input_dev; ts.dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); ts.dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); input_set_abs_params(ts.dev, ABS_X, 0, 0x3FF, 0, 0); input_set_abs_params(ts.dev, ABS_Y, 0, 0x3FF, 0, 0); input_set_abs_params(ts.dev, ABS_PRESSURE, 0, 1, 0, 0);
ts.dev->name = s3c2410ts_name; ts.dev->id.bustype = BUS_RS232; ts.dev->id.vendor = 0xDEAD; ts.dev->id.product = 0xBEEF; ts.dev->id.version = S3C2410TSVERSION; ts.state = TS_STATE_STANDBY;//设置ts状态为就绪
ts.event_fifo = kfifo_alloc(TS_EVENT_FIFO_SIZE, GFP_KERNEL, NULL);//为event队列申请内存空间
if (IS_ERR(ts.event_fifo)) { ret = -EIO; goto bail2; }
/* create the filter chain set up for the 2 coordinates we produce */ ts.chain = ts_filter_chain_create(pdev, info->filter_config, 2);//针对android的,建立filter_chain
if (IS_ERR(ts.chain)) goto bail2;
ts_filter_chain_clear(ts.chain);
/* Get irqs */ if (request_irq(IRQ_ADC, stylus_action, IRQF_SAMPLE_RANDOM, "s3c2410_action", ts.dev)) { dev_err(&pdev->dev, "Could not allocate ts IRQ_ADC !\n"); iounmap(base_addr); ret = -EIO; goto bail3; } if (request_irq(IRQ_TC, stylus_updown, IRQF_SAMPLE_RANDOM, "s3c2410_action", ts.dev)) { dev_err(&pdev->dev, "Could not allocate ts IRQ_TC !\n"); free_irq(IRQ_ADC, ts.dev); iounmap(base_addr); ret = -EIO; goto bail4; }
dev_info(&pdev->dev, "Successfully loaded\n");
/* All went ok, so register to the input system */ rc = input_register_device(ts.dev); if (rc) { ret = -EIO; goto bail5; }
return 0;
bail5: free_irq(IRQ_TC, ts.dev); free_irq(IRQ_ADC, ts.dev); clk_disable(adc_clock); iounmap(base_addr); disable_irq(IRQ_TC); bail4: disable_irq(IRQ_ADC); bail3: ts_filter_chain_destroy(ts.chain); kfifo_free(ts.event_fifo); bail2: input_unregister_device(ts.dev); bail1: iounmap(base_addr); bail0:
return ret; }
|