1 /* 2 * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com> 3 * 4 * Original author: 5 * Ben Collins <bcollins@ubuntu.com> 6 * 7 * Additional work by: 8 * John Brooks <john.brooks@bluecherry.net> 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License as published by 12 * the Free Software Foundation; either version 2 of the License, or 13 * (at your option) any later version. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 */ 20 21 #include <linux/kernel.h> 22 #include <linux/fs.h> 23 #include <linux/delay.h> 24 #include <linux/uaccess.h> 25 26 #include "solo6x10.h" 27 28 static void solo_gpio_mode(struct solo_dev *solo_dev, 29 unsigned int port_mask, unsigned int mode) 30 { 31 int port; 32 unsigned int ret; 33 34 ret = solo_reg_read(solo_dev, SOLO_GPIO_CONFIG_0); 35 36 /* To set gpio */ 37 for (port = 0; port < 16; port++) { 38 if (!((1 << port) & port_mask)) 39 continue; 40 41 ret &= (~(3 << (port << 1))); 42 ret |= ((mode & 3) << (port << 1)); 43 } 44 45 solo_reg_write(solo_dev, SOLO_GPIO_CONFIG_0, ret); 46 47 /* To set extended gpio - sensor */ 48 ret = solo_reg_read(solo_dev, SOLO_GPIO_CONFIG_1); 49 50 for (port = 0; port < 16; port++) { 51 if (!((1 << (port + 16)) & port_mask)) 52 continue; 53 54 if (!mode) 55 ret &= ~(1 << port); 56 else 57 ret |= 1 << port; 58 } 59 60 solo_reg_write(solo_dev, SOLO_GPIO_CONFIG_1, ret); 61 } 62 63 static void solo_gpio_set(struct solo_dev *solo_dev, unsigned int value) 64 { 65 solo_reg_write(solo_dev, SOLO_GPIO_DATA_OUT, 66 solo_reg_read(solo_dev, SOLO_GPIO_DATA_OUT) | value); 67 } 68 69 static void solo_gpio_clear(struct solo_dev *solo_dev, unsigned int value) 70 { 71 solo_reg_write(solo_dev, SOLO_GPIO_DATA_OUT, 72 solo_reg_read(solo_dev, SOLO_GPIO_DATA_OUT) & ~value); 73 } 74 75 static void solo_gpio_config(struct solo_dev *solo_dev) 76 { 77 /* Video reset */ 78 solo_gpio_mode(solo_dev, 0x30, 1); 79 solo_gpio_clear(solo_dev, 0x30); 80 udelay(100); 81 solo_gpio_set(solo_dev, 0x30); 82 udelay(100); 83 84 /* Warning: Don't touch the next line unless you're sure of what 85 * you're doing: first four gpio [0-3] are used for video. */ 86 solo_gpio_mode(solo_dev, 0x0f, 2); 87 88 /* We use bit 8-15 of SOLO_GPIO_CONFIG_0 for relay purposes */ 89 solo_gpio_mode(solo_dev, 0xff00, 1); 90 91 /* Initially set relay status to 0 */ 92 solo_gpio_clear(solo_dev, 0xff00); 93 } 94 95 int solo_gpio_init(struct solo_dev *solo_dev) 96 { 97 solo_gpio_config(solo_dev); 98 return 0; 99 } 100 101 void solo_gpio_exit(struct solo_dev *solo_dev) 102 { 103 solo_gpio_clear(solo_dev, 0x30); 104 solo_gpio_config(solo_dev); 105 } 106