static struct dvb_frontend_ops m88ds3103_ops;
 
+/* write single register with mask */
+static int m88ds3103_update_bits(struct m88ds3103_dev *dev,
+                               u8 reg, u8 mask, u8 val)
+{
+       int ret;
+       u8 tmp;
+
+       /* no need for read if whole reg is written */
+       if (mask != 0xff) {
+               ret = regmap_bulk_read(dev->regmap, reg, &tmp, 1);
+               if (ret)
+                       return ret;
+
+               val &= mask;
+               tmp &= ~mask;
+               val |= tmp;
+       }
+
+       return regmap_bulk_write(dev->regmap, reg, &val, 1);
+}
+
 /* write reg val table using reg addr auto increment */
 static int m88ds3103_wr_reg_val_tab(struct m88ds3103_dev *dev,
                const struct m88ds3103_reg_val *tab, int tab_len)
                        u8tmp2 = 0x00; /* 0b00 */
                        break;
                }
-               ret = regmap_update_bits(dev->regmap, 0x22, 0xc0, u8tmp1 << 6);
+               ret = m88ds3103_update_bits(dev, 0x22, 0xc0, u8tmp1 << 6);
                if (ret)
                        goto err;
-               ret = regmap_update_bits(dev->regmap, 0x24, 0xc0, u8tmp2 << 6);
+               ret = m88ds3103_update_bits(dev, 0x24, 0xc0, u8tmp2 << 6);
                if (ret)
                        goto err;
        }
                        if (ret)
                                goto err;
                }
-               ret = regmap_update_bits(dev->regmap, 0x9d, 0x08, 0x08);
+               ret = m88ds3103_update_bits(dev, 0x9d, 0x08, 0x08);
                if (ret)
                        goto err;
                ret = regmap_write(dev->regmap, 0xf1, 0x01);
                if (ret)
                        goto err;
-               ret = regmap_update_bits(dev->regmap, 0x30, 0x80, 0x80);
+               ret = m88ds3103_update_bits(dev, 0x30, 0x80, 0x80);
                if (ret)
                        goto err;
        }
        switch (dev->cfg->ts_mode) {
        case M88DS3103_TS_SERIAL:
        case M88DS3103_TS_SERIAL_D7:
-               ret = regmap_update_bits(dev->regmap, 0x29, 0x20, u8tmp1);
+               ret = m88ds3103_update_bits(dev, 0x29, 0x20, u8tmp1);
                if (ret)
                        goto err;
                u8tmp1 = 0;
        if (ret)
                goto err;
 
-       ret = regmap_update_bits(dev->regmap, 0x4d, 0x02, dev->cfg->spec_inv << 1);
+       ret = m88ds3103_update_bits(dev, 0x4d, 0x02, dev->cfg->spec_inv << 1);
        if (ret)
                goto err;
 
-       ret = regmap_update_bits(dev->regmap, 0x30, 0x10, dev->cfg->agc_inv << 4);
+       ret = m88ds3103_update_bits(dev, 0x30, 0x10, dev->cfg->agc_inv << 4);
        if (ret)
                goto err;
 
        dev->warm = false;
 
        /* wake up device from sleep */
-       ret = regmap_update_bits(dev->regmap, 0x08, 0x01, 0x01);
+       ret = m88ds3103_update_bits(dev, 0x08, 0x01, 0x01);
        if (ret)
                goto err;
-       ret = regmap_update_bits(dev->regmap, 0x04, 0x01, 0x00);
+       ret = m88ds3103_update_bits(dev, 0x04, 0x01, 0x00);
        if (ret)
                goto err;
-       ret = regmap_update_bits(dev->regmap, 0x23, 0x10, 0x00);
+       ret = m88ds3103_update_bits(dev, 0x23, 0x10, 0x00);
        if (ret)
                goto err;
 
                utmp = 0x29;
        else
                utmp = 0x27;
-       ret = regmap_update_bits(dev->regmap, utmp, 0x01, 0x00);
+       ret = m88ds3103_update_bits(dev, utmp, 0x01, 0x00);
        if (ret)
                goto err;
 
        /* sleep */
-       ret = regmap_update_bits(dev->regmap, 0x08, 0x01, 0x00);
+       ret = m88ds3103_update_bits(dev, 0x08, 0x01, 0x00);
        if (ret)
                goto err;
-       ret = regmap_update_bits(dev->regmap, 0x04, 0x01, 0x01);
+       ret = m88ds3103_update_bits(dev, 0x04, 0x01, 0x01);
        if (ret)
                goto err;
-       ret = regmap_update_bits(dev->regmap, 0x23, 0x10, 0x10);
+       ret = m88ds3103_update_bits(dev, 0x23, 0x10, 0x10);
        if (ret)
                goto err;
 
        }
 
        utmp = tone << 7 | dev->cfg->envelope_mode << 5;
-       ret = regmap_update_bits(dev->regmap, 0xa2, 0xe0, utmp);
+       ret = m88ds3103_update_bits(dev, 0xa2, 0xe0, utmp);
        if (ret)
                goto err;
 
        utmp = 1 << 2;
-       ret = regmap_update_bits(dev->regmap, 0xa1, reg_a1_mask, utmp);
+       ret = m88ds3103_update_bits(dev, 0xa1, reg_a1_mask, utmp);
        if (ret)
                goto err;
 
        voltage_dis ^= dev->cfg->lnb_en_pol;
 
        utmp = voltage_dis << 1 | voltage_sel << 0;
-       ret = regmap_update_bits(dev->regmap, 0xa2, 0x03, utmp);
+       ret = m88ds3103_update_bits(dev, 0xa2, 0x03, utmp);
        if (ret)
                goto err;
 
        }
 
        utmp = dev->cfg->envelope_mode << 5;
-       ret = regmap_update_bits(dev->regmap, 0xa2, 0xe0, utmp);
+       ret = m88ds3103_update_bits(dev, 0xa2, 0xe0, utmp);
        if (ret)
                goto err;
 
        } else {
                dev_dbg(&client->dev, "diseqc tx timeout\n");
 
-               ret = regmap_update_bits(dev->regmap, 0xa1, 0xc0, 0x40);
+               ret = m88ds3103_update_bits(dev, 0xa1, 0xc0, 0x40);
                if (ret)
                        goto err;
        }
 
-       ret = regmap_update_bits(dev->regmap, 0xa2, 0xc0, 0x80);
+       ret = m88ds3103_update_bits(dev, 0xa2, 0xc0, 0x80);
        if (ret)
                goto err;
 
        }
 
        utmp = dev->cfg->envelope_mode << 5;
-       ret = regmap_update_bits(dev->regmap, 0xa2, 0xe0, utmp);
+       ret = m88ds3103_update_bits(dev, 0xa2, 0xe0, utmp);
        if (ret)
                goto err;
 
        } else {
                dev_dbg(&client->dev, "diseqc tx timeout\n");
 
-               ret = regmap_update_bits(dev->regmap, 0xa1, 0xc0, 0x40);
+               ret = m88ds3103_update_bits(dev, 0xa1, 0xc0, 0x40);
                if (ret)
                        goto err;
        }
 
-       ret = regmap_update_bits(dev->regmap, 0xa2, 0xc0, 0x80);
+       ret = m88ds3103_update_bits(dev, 0xa2, 0xc0, 0x80);
        if (ret)
                goto err;
 
                goto err_kfree;
 
        /* sleep */
-       ret = regmap_update_bits(dev->regmap, 0x08, 0x01, 0x00);
+       ret = m88ds3103_update_bits(dev, 0x08, 0x01, 0x00);
        if (ret)
                goto err_kfree;
-       ret = regmap_update_bits(dev->regmap, 0x04, 0x01, 0x01);
+       ret = m88ds3103_update_bits(dev, 0x04, 0x01, 0x01);
        if (ret)
                goto err_kfree;
-       ret = regmap_update_bits(dev->regmap, 0x23, 0x10, 0x10);
+       ret = m88ds3103_update_bits(dev, 0x23, 0x10, 0x10);
        if (ret)
                goto err_kfree;