+static int rk616_codec_parse_gpio(struct device *dev,
+ struct device_node *node, int *gpio, char *name)
+{
+ enum of_gpio_flags flags;
+ int ret;
+
+ *gpio = of_get_named_gpio_flags(node, name, 0, &flags);
+ if (*gpio < 0) {
+ printk("%s : %s is NULL!\n", __func__, name);
+ *gpio = INVALID_GPIO;
+ } else {
+ ret = devm_gpio_request(dev, *gpio, name);
+ if(ret < 0){
+ printk("%s() %s request ERROR\n", __FUNCTION__, name);
+ return ret;
+ }
+ ret = gpio_direction_output(*gpio , flags); //set gpio to low level
+ if(ret < 0){
+ printk("%s() %s set ERROR\n", __FUNCTION__, name);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+/*
+dts:
+ rk616-codec {
+ spk-ctl-gpio = <&gpio2 GPIO_D7 GPIO_ACTIVE_HIGH>;
+ hp-ctl-gpio = <&gpio2 GPIO_D7 GPIO_ACTIVE_HIGH>;
+ //rcv-ctl-gpio = <&gpio2 GPIO_D7 GPIO_ACTIVE_HIGH>;
+ //mic-sel-gpio = <&gpio2 GPIO_D7 GPIO_ACTIVE_HIGH>;
+
+ //delay for MOSFET or SPK power amplifier chip(ms)
+ spk-amplifier-delay = <150>;
+ hp-mosfet-delay = <50>;
+
+ //hp-mic-capture-from-linein; //If hpmic is connected to linein, set this.
+ //hp-mic-capture-from-mic2in; //If hpmic is connected to mic2, set this.
+ //virtual-hp-gnd; //If hp gnd is not connected to gnd(0V), set this.
+
+ //volume setting: 0 ~ 31, -18dB ~ 28.5dB, Step: 1.5dB
+ skp-volume = <24>;
+ hp-volume = <24>;
+ capture-volume = <24>;
+ };
+*/
+#ifdef CONFIG_OF
+static int rk616_codec_parse_dt_property(struct device *dev,
+ struct rk616_codec_priv *rk616)
+{
+ struct device_node *node = dev->of_node;
+ int ret;
+
+ DBG("%s()\n", __FUNCTION__);
+
+ if (!node) {
+ printk("%s() dev->of_node is NULL\n", __FUNCTION__);
+ return -ENODEV;
+ }
+
+ node = of_get_child_by_name(dev->of_node, "rk616-codec");
+ if (!node) {
+ printk("%s() Can not get child: rk616-codec\n", __FUNCTION__);
+ return -ENODEV;
+ }
+
+ ret = rk616_codec_parse_gpio(dev, node, &rk616->spk_ctl_gpio, "spk-ctl-gpio");
+ if(ret < 0){
+ printk("%s() parse gpio : spk-ctl-gpio ERROR\n", __FUNCTION__);
+ return ret;
+ }
+
+ ret = rk616_codec_parse_gpio(dev, node, &rk616->hp_ctl_gpio, "hp-ctl-gpio");
+ if((ret < 0) && (rk616->hp_ctl_gpio != rk616->spk_ctl_gpio)){
+ printk("%s() parse gpio : hp-ctl-gpio ERROR\n", __FUNCTION__);
+ return ret;
+ }
+
+ ret = rk616_codec_parse_gpio(dev, node, &rk616->rcv_ctl_gpio, "rcv-ctl-gpio");
+ if(ret < 0){
+ printk("%s() parse gpio : rcv-ctl-gpio ERROR\n", __FUNCTION__);
+ return ret;
+ }
+
+ ret = rk616_codec_parse_gpio(dev, node, &rk616->mic_sel_gpio, "mic-sel-gpio");
+ if(ret < 0){
+ printk("%s() parse gpio : mic-sel-gpio ERROR\n", __FUNCTION__);
+ return ret;
+ }
+
+ ret = of_property_read_u32(node, "spk-amplifier-delay", &rk616->spk_amp_delay);
+ if (ret < 0) {
+ DBG("%s() Can not read property spk-amplifier-delay\n", __FUNCTION__);
+ rk616->spk_amp_delay = 0;
+ }
+
+ ret = of_property_read_u32(node, "hp-mosfet-delay", &rk616->hp_mos_delay);
+ if (ret < 0) {
+ DBG("%s() Can not read property hp-mosfet-delay\n", __FUNCTION__);
+ rk616->hp_mos_delay = 0;
+ }
+
+ rk616->hpmic_from_linein = !!of_get_property(node, "hp-mic-capture-from-linein", NULL);
+ rk616->hpmic_from_mic2in = !!of_get_property(node, "hp-mic-capture-from-mic2in", NULL);
+ rk616->virtual_gnd = !!of_get_property(node, "virtual-hp-gnd", NULL);
+
+ ret = of_property_read_u32(node, "skp-volume", &rk616->spk_volume);
+ if (ret < 0) {
+ DBG("%s() Can not read property skp-volume\n", __FUNCTION__);
+ rk616->spk_volume = 24;
+ }
+
+ ret = of_property_read_u32(node, "hp-volume", &rk616->hp_volume);
+ if (ret < 0) {
+ DBG("%s() Can not read property hp-volume\n", __FUNCTION__);
+ rk616->hp_volume = 24;
+ }
+
+ ret = of_property_read_u32(node, "capture-volume", &rk616->capture_volume);
+ if (ret < 0) {
+ DBG("%s() Can not read property capture-volume\n", __FUNCTION__);
+ rk616->spk_volume = 24;
+ }
+
+ return 0;
+}
+#else
+static int rk616_codec_parse_dt_property(struct device *dev,
+ struct rk616_codec_priv *rk616)
+{
+ return -ENOSYS;
+}
+#endif //#ifdef CONFIG_OF
+