.. | .. |
---|
9 | 9 | * 3. add version control. |
---|
10 | 10 | * V0.0X01.0X02 |
---|
11 | 11 | * 1. fix otp info null issue. |
---|
| 12 | + * V0.0X01.0X03 |
---|
| 13 | + * 1. add buf read optimize otp read speed. |
---|
| 14 | + * 2. add mutex for otp read. |
---|
12 | 15 | */ |
---|
13 | | - |
---|
| 16 | +//#define DEBUG |
---|
14 | 17 | #include <linux/delay.h> |
---|
15 | 18 | #include <linux/i2c.h> |
---|
16 | 19 | #include <linux/module.h> |
---|
.. | .. |
---|
24 | 27 | #include <linux/version.h> |
---|
25 | 28 | #include "otp_eeprom.h" |
---|
26 | 29 | |
---|
27 | | -#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x02) |
---|
| 30 | +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x03) |
---|
28 | 31 | #define DEVICE_NAME "otp_eeprom" |
---|
29 | 32 | |
---|
30 | 33 | static inline struct eeprom_device |
---|
.. | .. |
---|
64 | 67 | return -EIO; |
---|
65 | 68 | |
---|
66 | 69 | *val = be32_to_cpu(data_be); |
---|
| 70 | + |
---|
| 71 | + return 0; |
---|
| 72 | +} |
---|
| 73 | + |
---|
| 74 | +/* Read registers buffers at a time */ |
---|
| 75 | +static int read_reg_otp_buf(struct i2c_client *client, u16 reg, |
---|
| 76 | + unsigned int len, u8 *buf) |
---|
| 77 | +{ |
---|
| 78 | + struct i2c_msg msgs[2]; |
---|
| 79 | + __be16 reg_addr_be = cpu_to_be16(reg); |
---|
| 80 | + int ret; |
---|
| 81 | + |
---|
| 82 | + /* Write register address */ |
---|
| 83 | + msgs[0].addr = client->addr; |
---|
| 84 | + msgs[0].flags = 0; |
---|
| 85 | + msgs[0].len = 2; |
---|
| 86 | + msgs[0].buf = (u8 *)®_addr_be; |
---|
| 87 | + |
---|
| 88 | + /* Read data from register */ |
---|
| 89 | + msgs[1].addr = client->addr; |
---|
| 90 | + msgs[1].flags = I2C_M_RD; |
---|
| 91 | + msgs[1].len = len; |
---|
| 92 | + msgs[1].buf = buf; |
---|
| 93 | + |
---|
| 94 | + ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); |
---|
| 95 | + if (ret != ARRAY_SIZE(msgs)) |
---|
| 96 | + return -EIO; |
---|
67 | 97 | |
---|
68 | 98 | return 0; |
---|
69 | 99 | } |
---|
.. | .. |
---|
448 | 478 | struct i2c_client *client = eeprom_dev->client; |
---|
449 | 479 | struct device *dev = &eeprom_dev->client->dev; |
---|
450 | 480 | u32 checksum = 0; |
---|
451 | | - u32 temp = 0; |
---|
| 481 | + u8 *lsc_buf; |
---|
452 | 482 | int i = 0; |
---|
453 | 483 | int ret = 0; |
---|
454 | 484 | #ifdef DEBUG |
---|
455 | 485 | int w, h, j; |
---|
456 | 486 | #endif |
---|
| 487 | + |
---|
| 488 | + lsc_buf = kzalloc(LSC_DATA_SIZE, GFP_KERNEL); |
---|
| 489 | + if (!lsc_buf) { |
---|
| 490 | + dev_err(dev, "%s ENOMEM!\n", __func__); |
---|
| 491 | + return; |
---|
| 492 | + } |
---|
457 | 493 | |
---|
458 | 494 | ret = read_reg_otp(client, base_addr, |
---|
459 | 495 | 4, &otp_ptr->lsc_data.size); |
---|
.. | .. |
---|
463 | 499 | 2, &otp_ptr->lsc_data.version); |
---|
464 | 500 | checksum += otp_ptr->lsc_data.version; |
---|
465 | 501 | base_addr += 2; |
---|
| 502 | + |
---|
| 503 | + ret |= read_reg_otp_buf(client, base_addr, |
---|
| 504 | + LSC_DATA_SIZE, lsc_buf); |
---|
| 505 | + base_addr += LSC_DATA_SIZE; |
---|
| 506 | + |
---|
466 | 507 | for (i = 0; i < LSC_DATA_SIZE; i++) { |
---|
467 | | - ret |= read_reg_otp(client, base_addr, |
---|
468 | | - 1, &temp); |
---|
469 | | - otp_ptr->lsc_data.data[i] = temp; |
---|
470 | | - checksum += temp; |
---|
471 | | - base_addr += 1; |
---|
| 508 | + otp_ptr->lsc_data.data[i] = lsc_buf[i]; |
---|
| 509 | + checksum += lsc_buf[i]; |
---|
472 | 510 | } |
---|
473 | 511 | otp_ptr->lsc_data.table_size = LSC_DATA_SIZE; |
---|
474 | 512 | #ifdef DEBUG |
---|
.. | .. |
---|
482 | 520 | dev_info(dev, "\n"); |
---|
483 | 521 | } |
---|
484 | 522 | #endif |
---|
| 523 | + |
---|
| 524 | + memset(lsc_buf, 0, LSC_DATA_SIZE); |
---|
| 525 | + ret |= read_reg_otp_buf(client, base_addr, |
---|
| 526 | + RK_LSC_RESERVED_SIZE, lsc_buf); |
---|
| 527 | + |
---|
485 | 528 | for (i = 0; i < RK_LSC_RESERVED_SIZE; i++) { |
---|
486 | | - ret |= read_reg_otp(client, base_addr, |
---|
487 | | - 1, &temp); |
---|
488 | | - checksum += temp; |
---|
489 | | - base_addr += 1; |
---|
| 529 | + checksum += lsc_buf[i]; |
---|
490 | 530 | } |
---|
| 531 | + base_addr += RK_LSC_RESERVED_SIZE; |
---|
491 | 532 | ret |= read_reg_otp(client, base_addr, |
---|
492 | 533 | 1, &otp_ptr->lsc_data.checksum); |
---|
493 | 534 | if ((checksum % 255 + 1) == otp_ptr->lsc_data.checksum && (!ret)) { |
---|
.. | .. |
---|
502 | 543 | (int)(checksum % 255 + 1), |
---|
503 | 544 | (int)otp_ptr->lsc_data.checksum); |
---|
504 | 545 | } |
---|
| 546 | + kfree(lsc_buf); |
---|
505 | 547 | } |
---|
506 | 548 | |
---|
507 | 549 | static void rkotp_read_pdaf(struct eeprom_device *eeprom_dev, |
---|
.. | .. |
---|
511 | 553 | struct i2c_client *client = eeprom_dev->client; |
---|
512 | 554 | struct device *dev = &eeprom_dev->client->dev; |
---|
513 | 555 | u32 checksum = 0; |
---|
514 | | - u32 temp = 0; |
---|
| 556 | + u8 *pdaf_buf; |
---|
515 | 557 | int i = 0; |
---|
516 | 558 | int ret = 0; |
---|
517 | 559 | #ifdef DEBUG |
---|
518 | 560 | int w, h, j; |
---|
519 | 561 | #endif |
---|
| 562 | + |
---|
| 563 | + pdaf_buf = kzalloc(RK_GAINMAP_SIZE, GFP_KERNEL); |
---|
| 564 | + if (!pdaf_buf) { |
---|
| 565 | + dev_err(dev, "%s ENOMEM!\n", __func__); |
---|
| 566 | + return; |
---|
| 567 | + } |
---|
520 | 568 | |
---|
521 | 569 | ret = read_reg_otp(client, base_addr, |
---|
522 | 570 | 4, &otp_ptr->pdaf_data.size); |
---|
.. | .. |
---|
534 | 582 | 1, &otp_ptr->pdaf_data.gainmap_height); |
---|
535 | 583 | checksum += otp_ptr->pdaf_data.gainmap_height; |
---|
536 | 584 | base_addr += 1; |
---|
| 585 | + |
---|
| 586 | + ret |= read_reg_otp_buf(client, base_addr, |
---|
| 587 | + RK_GAINMAP_SIZE, pdaf_buf); |
---|
| 588 | + base_addr += RK_GAINMAP_SIZE; |
---|
| 589 | + |
---|
537 | 590 | for (i = 0; i < RK_GAINMAP_SIZE; i++) { |
---|
538 | | - ret |= read_reg_otp(client, base_addr, |
---|
539 | | - 1, &otp_ptr->pdaf_data.gainmap[i]); |
---|
| 591 | + otp_ptr->pdaf_data.gainmap[i] = pdaf_buf[i]; |
---|
540 | 592 | checksum += otp_ptr->pdaf_data.gainmap[i]; |
---|
541 | | - base_addr += 1; |
---|
542 | 593 | } |
---|
543 | 594 | #ifdef DEBUG |
---|
544 | 595 | w = 64; |
---|
.. | .. |
---|
571 | 622 | 1, &otp_ptr->pdaf_data.dccmap_height); |
---|
572 | 623 | checksum += otp_ptr->pdaf_data.dccmap_height; |
---|
573 | 624 | base_addr += 1; |
---|
| 625 | + |
---|
| 626 | + memset(pdaf_buf, 0, RK_DCCMAP_SIZE); |
---|
| 627 | + ret |= read_reg_otp_buf(client, base_addr, |
---|
| 628 | + RK_DCCMAP_SIZE, pdaf_buf); |
---|
| 629 | + |
---|
574 | 630 | for (i = 0; i < RK_DCCMAP_SIZE; i++) { |
---|
575 | | - ret |= read_reg_otp(client, base_addr, |
---|
576 | | - 1, &otp_ptr->pdaf_data.dccmap[i]); |
---|
| 631 | + otp_ptr->pdaf_data.dccmap[i] = pdaf_buf[i]; |
---|
577 | 632 | checksum += otp_ptr->pdaf_data.dccmap[i]; |
---|
578 | | - base_addr += 1; |
---|
579 | 633 | } |
---|
| 634 | + base_addr += RK_DCCMAP_SIZE; |
---|
| 635 | + |
---|
580 | 636 | #ifdef DEBUG |
---|
581 | 637 | w = 32; |
---|
582 | 638 | h = 16; |
---|
.. | .. |
---|
592 | 648 | 1, &otp_ptr->pdaf_data.dccmap_checksum); |
---|
593 | 649 | checksum += otp_ptr->pdaf_data.dccmap_checksum; |
---|
594 | 650 | base_addr += 1; |
---|
| 651 | + |
---|
| 652 | + ret |= read_reg_otp(client, base_addr, |
---|
| 653 | + 2, &otp_ptr->pdaf_data.pd_offset); |
---|
| 654 | + checksum += otp_ptr->pdaf_data.pd_offset; |
---|
| 655 | + base_addr += 2; |
---|
| 656 | + |
---|
| 657 | + memset(pdaf_buf, 0, RK_PDAF_RESERVED_SIZE); |
---|
| 658 | + ret |= read_reg_otp_buf(client, base_addr, |
---|
| 659 | + RK_PDAF_RESERVED_SIZE, pdaf_buf); |
---|
| 660 | + |
---|
595 | 661 | for (i = 0; i < RK_PDAF_RESERVED_SIZE; i++) { |
---|
596 | | - ret |= read_reg_otp(client, base_addr, |
---|
597 | | - 1, &temp); |
---|
598 | | - checksum += temp; |
---|
599 | | - base_addr += 1; |
---|
| 662 | + checksum += pdaf_buf[i]; |
---|
600 | 663 | } |
---|
| 664 | + base_addr += RK_PDAF_RESERVED_SIZE; |
---|
| 665 | + |
---|
601 | 666 | ret |= read_reg_otp(client, base_addr, |
---|
602 | 667 | 1, &otp_ptr->pdaf_data.checksum); |
---|
603 | 668 | if ((checksum % 255 + 1) == otp_ptr->pdaf_data.checksum && (!ret)) { |
---|
.. | .. |
---|
612 | 677 | (int)(checksum % 255 + 1), |
---|
613 | 678 | (int)otp_ptr->pdaf_data.checksum); |
---|
614 | 679 | } |
---|
| 680 | + kfree(pdaf_buf); |
---|
615 | 681 | } |
---|
616 | 682 | |
---|
617 | 683 | static void rkotp_read_af(struct eeprom_device *eeprom_dev, |
---|
.. | .. |
---|
738 | 804 | u8 vendor_flag = 0; |
---|
739 | 805 | struct i2c_client *client = eeprom_dev->client; |
---|
740 | 806 | |
---|
| 807 | + mutex_lock(&eeprom_dev->mutex); |
---|
741 | 808 | vendor_flag = get_vendor_flag(client); |
---|
742 | 809 | if (vendor_flag == 0x80) |
---|
743 | 810 | otp_read_data(eeprom_dev); |
---|
.. | .. |
---|
745 | 812 | rkotp_read_data(eeprom_dev); |
---|
746 | 813 | else { |
---|
747 | 814 | dev_warn(&client->dev, "no vendor flag infos!\n"); |
---|
| 815 | + mutex_unlock(&eeprom_dev->mutex); |
---|
748 | 816 | return -1; |
---|
749 | 817 | } |
---|
| 818 | + |
---|
| 819 | + mutex_unlock(&eeprom_dev->mutex); |
---|
750 | 820 | return 0; |
---|
751 | 821 | } |
---|
752 | 822 | |
---|
.. | .. |
---|
866 | 936 | seq_printf(p, "flag=%d;\n", dev->otp->pdaf_data.flag); |
---|
867 | 937 | seq_printf(p, "gainmap_width=%d;\n", gainmap_w); |
---|
868 | 938 | seq_printf(p, "gainmap_height=%d;\n", gainmap_h); |
---|
869 | | - |
---|
| 939 | + seq_printf(p, "pd_offset=%d\n", dev->otp->pdaf_data.pd_offset); |
---|
870 | 940 | seq_printf(p, "gainmap_table=\n"); |
---|
871 | 941 | for (i = 0; i < gainmap_h; i++) { |
---|
872 | 942 | for (j = 0; j < gainmap_w; j++) { |
---|
.. | .. |
---|
917 | 987 | return single_open(file, otp_eeprom_show, data); |
---|
918 | 988 | } |
---|
919 | 989 | |
---|
920 | | -static const struct file_operations ops = { |
---|
921 | | - .owner = THIS_MODULE, |
---|
922 | | - .open = eeprom_open, |
---|
923 | | - .read = seq_read, |
---|
924 | | - .llseek = seq_lseek, |
---|
925 | | - .release = single_release, |
---|
| 990 | +static const struct proc_ops ops = { |
---|
| 991 | + .proc_open = eeprom_open, |
---|
| 992 | + .proc_read = seq_read, |
---|
| 993 | + .proc_lseek = seq_lseek, |
---|
| 994 | + .proc_release = single_release, |
---|
926 | 995 | }; |
---|
927 | 996 | |
---|
928 | 997 | static int eeprom_proc_init(struct eeprom_device *dev) |
---|
.. | .. |
---|
974 | 1043 | dev_err(&client->dev, "Probe failed\n"); |
---|
975 | 1044 | return -ENOMEM; |
---|
976 | 1045 | } |
---|
| 1046 | + mutex_init(&eeprom_dev->mutex); |
---|
977 | 1047 | v4l2_i2c_subdev_init(&eeprom_dev->sd, |
---|
978 | 1048 | client, &eeprom_ops); |
---|
979 | 1049 | eeprom_dev->client = client; |
---|
.. | .. |
---|
995 | 1065 | struct eeprom_device *eeprom_dev = |
---|
996 | 1066 | sd_to_eeprom(sd); |
---|
997 | 1067 | kfree(eeprom_dev->otp); |
---|
| 1068 | + mutex_destroy(&eeprom_dev->mutex); |
---|
998 | 1069 | pm_runtime_disable(&client->dev); |
---|
999 | 1070 | eeprom_subdev_cleanup(eeprom_dev); |
---|
1000 | 1071 | eeprom_proc_cleanup(eeprom_dev); |
---|